Vous êtes sur la page 1sur 169

,.....---------------------------..

A BEGINNER'S GUIDE
TO USING PIC
MICROCONTROLLERS
FROM

VERSION 3.1

David Benson
Ple'n

A BEGINNER'S GUIDE TO USING


PIC MICROCONTROLLERS
FROM

DAVID BENSON

VERSION 3.1
NOTICE

The material presented in this book is for the education and


amusement of students, hobbyists, technicians and engineers.
Every effort has been made to assure the accuracy of this infor-
mation and its suitability for this purpose. Square 1 Electronics
and the author assume no responsibility for the suitability of this
information for any application nor do we assume any liability
resulting from use of this information. No patent liability is
assumed for use of the information contained herein.

All rights reserved. No part of this book shall be reproduced or


transmitted by any means (including photo copying) without
written permission from Square 1 Electronics and the author.

Copyright © 1997 Revised April, 1999

TRADEMARKS

PIC is a registered trademark of Microchip Technology Inc. in


the U.S.A.
PICmicro is a registered trademark of Microchip Technology, Inc.
PIC16j17 is a registered trademark of Microchip Technology, Inc.
MPLAB is a registered trademark of Microchip Technology, Inc.
MPASM is a registered trademark of Microchip Technology, Inc.
MPSIM is a registered trademark of Microchip Technology, Inc.
PICSTART Plus is a registered trademark of Microchip Technology, Inc.
MS-DOS is a registered trademark of Microsoft Corporation.
Windows is a registered trademark of Microsoft Corporation.

ISBN 0-9654162-0-8

PUBLISHER

Square 1 Electronics
P.O. Box 501
Kelseyville,CA 95451 U.S.A.

voice (707)279-8881
FAX (707)279-8883
EMAIL sqone@pacific.net
http://www.sq-1.com
A BEGINNER'S GUIDE TO USING
PIC MICROCONTROLLERS
FROM

INTRODUCTION 1
PIC PRODUCT OVERVIEW 3
PIC16F84 5
Pins and Functions 5
Package 5
Clock Oscillator 6
Configuration bits 7
Reset 7
Ports 8
Special Features 8
Watchdog Timer 8
Power-up Timer 8
Sleep Mode 8
PIC16 Architecture 9
Program Memory 9
Weird Hex Notation 9
Fi le Registers 10
Working Register (W) 11
Option Register 11
Stack 11
Reset Vector 11
Interrupt Vector 11
Option Register 12
Program Counter 13
Status Register 15

CIRCUIT FOR EXPERIMENTS 16

'84 On A Board 17

CHOOSING DEVELOPMENT TOOLS 20


MPLAB/Windows vs. MPASM/MS-DOS 20
Choosing A Device Programmer 20
USING AN ASSEMBLER 22
Source Code For The Assembler 22
Semicolon (;) 23
Tabs 24
Style 25
Headers 26
Labels 26
Equates 27
Literals 28
Origin 29
End 30
Program Format 30
Files Used By Assembler 31
Files Created By Assembler 31
Preventing Some Gotchas 33

USING THE MS-DOS BASED MPASM ASSEMBLER 34


How To Assemble A Program 34

MPLAB OVERVIEW - GETTING STARTED 37


Using MPLAB - Getting Started 37
Toolbars 37
Select Development Mode And Device Type 38
Project 38
Te xt Editor 39
Edit Project 39
Assembler 40
Mo r e MPLAB Operations 40

PROGRAMMING A DEVICE 41

WRITI NG PROGRAMS 43

Programming Concepts 43
Instruction Set 46
Weird Move Instruction 48
Instruction Format For The Assembl~r 49
Byte -Oriented I nstructions 49
Bit-Oriented Instructions 50
Literal Instructions 50
Control Instructions (CALL and GOTO) 50
Destination Designato r (d) 51
He xadecimal Numbers vs . MPASM Assembler 52
Binary And Decimal Numbers vs. MPASM Assembler 53
ASCII Characters v s . MPASM As s e mbl e r 53
Addressing Modes 54
Immediate addressing 54
Direct Ad dre s s ing 54
Indirect Ad dres s i n g 54
Re l a t ive Addressi ng 55
Use Of The RETLW Inst ruction For Accessing 56
Tables of Data Via Re l a t i v e Addressing
using The Ports 58
Data Direction 58
Port Read/Write 58
Flags 59
Simple Data Transfers 59
Loop - Endless 61
Loop With a Counter 62
Loop Until 65
Comparisons 66
Bit Manipulation Using Bit Manipulation 69
Instructions
Bit Manipulation Using Logic Instructions 71
Using Bit Manipulation 73
Sequencing 77
Subroutines 80
Time Delay Loop 82
Lookup Tables 91
INTERRUPTS 94
Interrupt Control Register 95
Interrupt Sources 96
External 96
Timer/Counter 96
Port B Interrupt On Change - Bits 7,6,5,4 97
Global Interrupt Enable Flag 97
Saving Status During An Interrupt (Context Saving) 97
Where To Put The Interrupt Service Routine 98
Interrupt Latency 99
Multiple Interrupt Sources 100
Example - External Interrupt 101
TIMING AND COUNTING 107
Digital Output Waveforms 107
Timing And Counting Using The PIC16F84's TMRO 108
On-Board Timer/Counter
Prescaler 110
Changing Pres caler Assignment 111
Using The Timer/Counter 112
Timer/Counter Experiments 113
Digital Output Using TMRO - Internal Clock 113
Single Time Interval - Internal Clock 115
Single Time Interval - External Clock 118
Free Running Mode - Internal Clock 121
Free Running Mode - External Clock 125
Counting Events (Pulses) 126
PIC16C54 131

Pins And Functions 132


Packages 1 32
Clock Oscillator 133
Configuration bits 133
Ports 133
Architecture 1 34
Program Memory 1 34
File Registers 13 4
Stack 1 35
Reset Vector 13 5
Program Counter 1 36
Option Registe r 136
Status Register 13 7
No Timer/Counter Overfl ow Interrupt/Flag Out put 13 7
Fewer Instructions 13 7
PIC16C54 Programming Examp le 138
Timing And Counting 139
Timer/Counter Description 1 41
Using The Timer/Counter 142
Timer/Counter Experiment 142
MENDING OUR WAYS 143

Sink vs. Source 143


File Register Bank Switching 144
Bank Switching Demo 145
Interrupts And Bank Switching 1 48
Program Memory Paging 1 48
Include Files 1 48

I/O CONVERSION 151

Input Conversion 15 1
Output Conversion 15 4

MORE PIC'n BOOKS 157

APPENDICES
Appendi x A - Sources 159
Appendi x B - Hexadecimal Numbers 161
Appendi x C - Program Listings vs. Page Number 1 62
INTRODUCTION

The PIC was originally designed as a Peripheral Interface Controller (PIC) for a l ri-bit micro-
processor. It was essentially an I/O controller and was designed to be very fast. It had a small
microcoded instruction set. This design became the basis for Microchip Technology's
PICI6C5X family of micro controllers.

The PICI6F84 (or PICI6F84A) microcontroller is unique because its program memory is made
using Flash technology. It can be programmed, tested in-circuit and reprogrammed if neces sary
in a matter of a few minutes and without the need for a UV EPROM eraser. It is a small device
(18-pin), readily available to all including hobbyists and students at a cost of $6.00 (at this writ-
ing) in single quantity.

The PICI6F84 replaces the PICI6C84 which will soon be obsolete.

Think of the PIC I6F84 as a custom I/O handler. It looks at its inputs and, based on what it sees,
it sends signals out its outputs. You can customize it to do what you want via programming. It
is not a heavy duty number cruncher or data manipulator.

The MPASM (tm) assembler from Microchip Technology (manufactu rer of PIC family) is the
PIC assembler of choice for use in this book because:

• It is free from Microchip.


• Most people who are into PICs speak "MPASM".
• Most examples in magazines and on the Internet are written
in the MPASM dialect.
• It is included in MPLAB (tm), a popular development software package (available
free from Microchip).

A variety of programmers are available for the PICI6F84 from indep endent programmer manu-
facturers (see sources in Appendix A). Some range in cost from $40 to $80. Some come with
their own assemblers but will accept hex files created by MPASM (detail s later).

Microchip makes the PICSTART Plus (tm) programmer which will program all PIC microcon-
trollers. The cost is currently about $200.

The PICI6F84, MPASM assembler (either stand alone or as part of MPLA B) and a low cost
PICI6F84 programmer make a very inexpensive development system and a great way to get
started creating microcontroller based projects.

What you learn using the PICI6F84 is directly applicable to the whole line of PIC microcon-
trollers. The appro ach taken with the PICI6F84 in the first part of book is backwards compati-
ble with the PICI6C54 (explained toward the end of the book). The hassles of file register bank
switching and program memory paging are avoided as they are confusing to a beginner but man-
ageable after some experience is gained.

1
Learn ing how PICs work and how to apply them involves study in three areas:

• IBM compatible computer use (as needed).


• Assembler.
• PIC itself.

PIC s are not easy to write code for by hand because they are not intuitive. Many instructions
requi re setting or clearing a bit to specify the destination for the result of executing the instruc-
tion. This is OK as an initial learning experience, but would become tedious very soon. So use
of "power tools" is essential. This means learning to use an IBM compatible computer if you
haven't already done so. It also means learning to use an assembler which converts English-like
readable instructions into machine language understood by the PIC itself.

Finally, learning about the PIC's inner workings is possible once use of the power tools is under-
stood.

The object is to make this process as easy and enjoyable as possible. Once you get through this
and you have programmed a PIC16F84 for the first time, a whole new world awaits. You will be
able to create more interesting projects and have more fun!

The usual approach to teaching the use of the PIC has been to get into all of the assembler com-
mands and then show advanced examples. There has been no simple example showing how to
get started. As usual, only 5 percent of this information is needed to get started, but which 5 per-
cent. The approach taken here will be to give you the 5 percent you need to get going .

The assumption is made that you know how to do the following on an IBM compatible comput-
er:

• Create a new directory called \PIC.


• Copy the contents of a floppy disk to the directory \PIC.
• Use a simple text editor to create a text file, save it, make a copy of it, print it, and
copy it to the directory \PIC.

2
PIC16/17 PRODUCT OVERVIEW

This book uses the PIC16F84 and later the PIC16C54 as examples to get you started. The
emphasis is on the base-line (12-bit core) and mid-range (14-bit core) products. The 12-bit core
designates the instruction word length. You really won't care how many bits there are in an
instruction word, but it is the basis on which Microchip divides up their product line. The fol-
lowing brief tables are for reference:

Base-Line Mid-Range

12-bit Core 14-bit Core


Stack Levels 2 8
Interrupts No Yes
Instructions 33 35 *
Serial Programming No Yes
File Registers 128 max ** 256 max **
Example PIC16C54 PIC16F84

* We will use 37 - details later


** Varies with part number

PARTS IS PARTS

As the Microchip rnicrocontroller product line grows, and I am glad that it is, the part numbering
convention/system seems to be getting a bit involved . Also, the microcontroller product line
designation has been changed from PIC16/17 (tm) to PICm icro (tm), Microchip is going to do
what it will. You and I, however, need a way to keep things straight between us. The real key to
sanity here is to recognize that there are three fundamental product groups in terms of how they
function and, to some extent, how program code must be written for them. The three product
groups have 12-bit, 14-bit and 16-bit cores. We don't really care how many bits are in an
instruction word. We just need to know which set of rules and features apply when writing code
for a selected chip. Here are some popular examples:

Device Core Size Pins

PIC12C508 12 8
12C671 14 8
16C5 4 12 18
16C55 4 14 18
16C63 14 28
16C71 14 18
16C74 14 40
1 6F8 4 14 18

3
In days gone by, the 12CXXX parts had 12-bit cores, the PIC16C5 whatever parts had 12-bit
cores, etc. But no more. Forget the part numbering scheme and look at the data book or sum-
mary for core size.

This book talks only about the 12-bit core base-line and 14-bit core mid-range parts . We will
use PIC16 to designate the 12 and 14-bit core parts for lack of anything better to do.

The PIC16C554 is pin-far-pin compatible with the very popular PIC16C54 and PIC16C54A and
currently sells for the same price! The PIC16C554 has a 14-bit core and the features that go
with it such as interrupts and an 8-level stack, plus 2.5 times the number of file registers. I
would guess that the 14-bit core parts will eventually (long term) replace the 12-bit core parts .

As an aside, notice that the PIC16C556A might be useful as a OTP version of the PIC16F84,
less the EEPROM data memory. Food for thought.

The PIC16C84 has been replaced by the PIC 16CF84. There is a PIC16F84A which is identical
to the PIC16F84 for our purposes and you can use either one.

Microchip is now publishing a Product Line Card revised quarterly which will tell you what's
new and what's current. I find it to be very useful.

4
PIC16F84

PINS AND FUNCTIONS

RA2 1 18 RA1
RA3 2 17 RAO
RA4!TOCKI 3 16 OSC1/CLK IN
MCLR 4 15 OSC2/CLK OUT
Vss 5 PIC16F84 14 Vdd
RBO/INT 6- 13 RB7
RB1 7- 12 RB6
RB2 8- 11 RB5
RB3 9- 10 RB4

The PICI6F84 is fabricated using CMOS technology. It consumes very little power and is fully
static meaning that the clock can be stopped and all register contents will be retained. The maxi-
mum sink or source current for a port at any given time is as follows:

Any I/O Pin Port A Port B

Sink current 25 rnA 80 rnA 150 rnA


Source current 20 rnA 50 rnA 100 rnA

Supply current is primarily a function of operating voltage, frequency and I/O pin loading and is
typically 2 rnA or so for a 4MHz clock oscillator. This drops to approximately 40 microamps in
the sleep mode.

Because the device is CMOS, all inputs must go somewhere. All unused inputs should be pulled
up to the supply voltage (usually +5 VDC).

PACKAGE

The PICI6F84 is available in an I8-pin DIP package suitable for the experimenter. The part
number is PICI6F84-04/p for the 4 MHz part.

5
CLOCK OSCILLATOR

Four different types of clock oscillators may be used with PIC16F84 parts in general. The clock
oscillator types are:

RC - resistor/capacitor.
XT - crystal or ceramic resonator - external clock.
HS - high speed crystal or ceramic resonator - external clock.
LP - low power crystal - external clock.

At programming time, the part must be told via configuration bits what type of oscillator it will
be connected to.

The details of various oscillator circuits and components are given in the Microchip data book.

One possible clock circuit for experimentation is a 4 MHz crystal-controlled oscillator in a can.
They are accurate, always start and the math required for designing time delay loops is simple.
The external clock frequency is divided by 4 internally, so the internal clock frequency is 1
MHz. Almost all instructions are executed in one instruction (internal clock) cycle or 1
microsecond in this case. This is plenty fast for experimenting. The oscillator type code is XT.

+5VDC J'L/"1.M..
....
r' OSC1
14
1 I 8
fosc/4'-- OSC2
4MHz
Clock
Oscillator
PIC16F84
1 1 -1-7
N.C.

Ceramic resonators with built-in capacitors are small and inexpensive while providing good
accuracy (+/- 1.3 percent or better). They look a lot like a small ceramic capacitor except for the
fact they have three leads. A typical device looks like this:

OSC1
,..---
OSC2
Note: Devices are symmetrical -
center lead connects to
ground, remaining 2 leads
connect to OSC1/0SC2
:DI~ PIC16F84
(doesn't matter which
is which). OSC1 OSC2 I-rl~
---
Ceramic Resonator

A standard frequency is 4.00 MHz which offers the advantages mentioned above. Use XT for
oscillator type. Keep the wires/traces short.

6
An RC clock circuit may also be used where cost is an issue and timing accuracy is not.
Examples are shown. The oscillator type code is RC.

+5VDC

t - - - - - - I OSC1

C fosc/4 ~ OSC2 R c fosc (approx)

T PIC16F84
10K
10K
10K 0.1
20 pf
220 pf
~ f
625 KHz
80 KHz
85 Hz

CONFIGURATION BITS

The configuration bits are located in Flash memory outside the main part of Flash memory used
for program storage. There are five configuration bits. Two select clock oscillator type, one is
the watchdog timer enable bit, one is the power-up timer enable bit and one is the code protec-
tion bit. The device programmer accesses these bits during the device programming procedure.

RESET

The PICl6F84 has built-in power-on reset which works as long as the power supply voltage
comes up quickly. Commonly the MCLR pin is merely tied to the power supply. A switch may
be used to regain control if things run away.

+5VDC

10K";:,-

Reset

PIC16F84

7
PORTS

Port A is 5 bits/lines wide and port B is 8 bits/lines wide or byte-wide. Each port line may be
individually programmed as an input line or output line. This is done using a special instruction
which matches a bit pattern with the port lines. A "0" associated with a port line makes it an
output, a "I" makes it an input. Examples follow.

The PIC16F84 has port data direction registers as many other microcontrollers do. The
PIC16C54 does not (more on this later). Using the port data direction registers involves file reg-
ister bank switching which I have chosen to avoid for now. Doing it in the manner I am about to
describe goes against the recommendation of Microchip (concerned about compatibility with
future products). My primary concern is to make learning about PIC16s as simple as possible.
So the initial programming examples will use an obsolete instruction (fRIS) to avoid having to
deal with bank switching at this early stage. A benefit of this is backward compatibility. You
will need to learn to use this technique if you choose to work with base-line parts (pIC16C5X
series).

Ignore the "Obsolete Instruction" warning messages generated by MPASM.

The Port B lines have weak pullup resistors on them which may be enabled or disabled under
software control. All 8 resistors are enabled/disabled as a group via the RBPU bit in the option
register. The pullup resistor on an individual port line is automatically turned off when that line
is configured as an output. The pullups are disabled on power-on reset.

Port A, bit 4 is shared with the external timer/counter input called TOCK!. As a digital input
line, the input is Schmitt trigger. As a digital output line, it is open drain, so a pullup resistor is
required. The output cannot source current, it can only sink current.

All unused port lines should be tied to the power supply (CMOS rule - all inputs must go some-
where). On reset, all port lines are inputs.

SPECIAL FEATURES

Watchdog Timer
The watchdog timer is useful in some control applications where a runaway program could
cau se a safety problem. We will not deal with it except to say that it is important to select
"watchdog timer off' when programming the configuration bits.

Power-up Timer
The power-up timer should be selected "ON" when programming the configuration bits.

Sleep Mode
The feature of the "sleep mode" is drastically reduced power consumption achieved by turning
off the main clock oscillator. .

8
PIC16 ARCHITECTURE

PIC16 microcontrollers have two separate blocks of memory; program memory and file regis-
ters.

Program Memory
The PICI6F84 program memory is 14 bits wide and lK words long. Program memory is
Flash. Program memory is read-only at run time. PIC16s can only execute code contained in
program memory.

Pointed To By -""" Program Memory


Reset Vector ~
OxOOO
001
Pointed To By --"'" 002
Interrupt Vector ~ 003
004

Ox3FF

A limited amount of data may be stored in program memory as part of RETLW instructions (see
programming chapter).

Weird Hex Notation


Some assembler listings show two-digit hexadecimal addresses in the form OXXX where the
upper case x's mean don't care. The "Ox" means hexadecimal. The Ox notation comes from the
C programming language. The main thing is, when you see OxOF, it means hexadecimal OF.
Ox004 means hexadecimal 004.

9
File Registers
The file registers are 8 bits wide with the exception of the PCLA1H register which is 5 bits
wide. The PIC16F84 has a 80 file register address space (OxOO - Ox4F), but not all addresses are
used.

File RegIsters

OxOO Indirect Address Indirect Address Pointer *


01 TMRO Timer/Counter
02 PCL Program Counter Low Order 8 Bits
03 Status Status Register - Flags
04 File Select Indirect Pointer
05 Port A Data Port A
06 Port B Data Port B
07
08 EEDATA (Iqnore)
09 EEADR (Iqnore)
OA PCLATH Program Counter Latch High Order 5 Bits
OB INTCON Interrupt Control
OC

General Purpose File Registers


Think Of This Area As RAM (Data Memory)

Note: Bank Switching And


Bank 1 Ignored
Ox4F

* Not Physically Irrplemented

Twelve file registers have specific dedicated purposes which will be of interest to you (to be
described later). 68 file registers are there for your use and may be thought of as RAM or data
memory for storing data during program execution.

Hex
Address
ill OxOO Indirect data addressing register.
See indirect addressing section in programming chapter.
f1 OxOl Timer/counter register (TMRO).
See timing and counting chapter.
f2 Ox02 Program counter low byte.
See relative addressing section in programming chapter.
f3 Ox03 Status word register.
f4 Ox04 File select register (FSR).
See indirect addressing section in programming chapter.
f5 Ox05 Port A - 5-bit, bits 5 - 7 are not implemented and read as O's.
f6 Ox06 Port B - 8-bit (bit 0 is also INT bit).
f7 Ox07 Not used.
f8 Ox08 EEDATA (Ignore - used in EEPROM data memory programming).

10
f9 Ox09 EEADR (Ignore - used in EEPROM data memory programming).
fA OxOA PCLATH - write buffer for upper 5 bits of program counter.
See relative addressing section in programming chapter.
fB OxOB INTCON - interrupt control register.
See interrupts chapter.
fC - OxOC- General purpose registers (RAM or data memory).
f4F Ox4F

Note: File registers at Ox81, Ox85 and Ox86 are in bank 1 and are ignored for now. Bank
switching is required to access them.

Working Register (W)

The PICl6F84 has an 8-bit working register called W. It is a lot like the accumulator in other
microcontrollers. Its use will be illustrated in the programming chapter.

Option Register

The option register controls the port B weak pullup resistors, interrupt signal edge select, the
prescaler for the timer/counter and watchdog timer (shared) and also the input to the
timer/counter.

Stack
The PIC16F84 has an 8-level stack separate from the other registers (not part of the file register
address space = data memory). It is used to save the program counter contents when subroutines
are called so the microcontroller will know where to resume program execution when returning
from the subroutine. This is also true of interrupts. There are no stack manipulation instructions
and the stack is not accessible to the programmer.

Reset Vector

On reset which occurs on power-up or when the reset switch is used to pull MCLR low, the
PIC16F84 will go to program memory location OxOOO where the first instruction is stored. It
then begins executing instructions stored sequentially in memory.

Interrupt Vector

The interrupt vector points to OxOO4, so if interrupts are used, the first instruction of the interrupt
service routine must be at that location.

11
OPTION REGISTER

7 6 5 43210

I RBPO IINTEDG I ToCS I TOSE IpSA I PS2 IPS1 IPSO I POR .. OxFF

~ Prescaler Value
Prescaler Value
PS2 PS1 pSO ::t..6Y
0 0 0 2
Prescaler Assignment 0 0 1 4
0- TMRO 0 1 0 8
1- WDT 0 1 1 16
1 0 0 32
- TMRO External Clock Edge Select 1 0 1 64
o - Increment On Rising Edge 1 1 0 128
1 - Increment On Falling Edge 1 1 1 256

~ TMRO Clock Source Select


o .. Internal Instruction Cycle Clock
1 - External Via TOCKI Pin

Interrupt Edge Select


o - Interrupt On Falling Edge
1 - Interrupt On Rising Edge

- Port B Pullup Enable


O-Enabled
1 .. Disabled

For ease of use while learning and for backward compatibility with the PIC16C54, we will think
of the PICl6F84 option register as a "buried" register (not included in the file register address
space and having no address) and will write to it using the OPTION instruction. Microchip con-
siders the OPTION instruction obsolete, but we won't let that bother us. All of this avoids file
register bank-switching which can be dealt with later.

The MPASM assembler may generate a warning message when you use the OPTION instruc-
tion. Don't let that bother you either.

12
To change the contents of the option register, we will use the OPTION instruction which loads
the contents of the W register into the option register.

movlw b'11000000' ;bit pattern defined


option ;sends bit pattern to
,· option register
;
,._-----------------------------------------------------
,· bit 7 = 1 port B pullups disabled
,· bit 6 = 1 interrupt on rising edge
,· bits 5,4,3,2,1,0 = 0 - details in
,· timing and counting chapter
i------------------------------------------------------

PROGRAM COUNTER

The PICl6F84 has a 13-bit program counter. GOTO and CALL instructions include an ll-bit
address which is enough for a 2K program memory address space. The PICl6F84 has lK of
program memory.

PCH PCl
12 11 10 9 8 7 0
[JTTT] U,-------,,-------,,-----,-------,,-----ITJ
I '---.- - -
'--v--'I
-----'
Included In OP Code
For PartsWith More Enough To Define 2K
Than2K (1 Page) PIC16F84 Has 1K
Of Progam Memory Program Memory

The program counter high (PCH) cannot be read or written to directly. It is loaded from a 5-bit
latch called program counter latch high or PCLATH.

PCLATH
43210

[JTTT]
L--y---J

I
For PartsWith More
Than2K (1 Page)
Of Progam Memory

13
For the 14-bit core parts (pICI6CXXX and PIC 16FXX but not including PICI6C5X), a program
memory page is defined as 2K (not 256 bytes as with many other 8-bit microcontrollers) because
2K can be accessed using the 11 address bits contained in GOTO and CALL instructions.

Since the PIC16F84 has lK or one-half page of program memory, we won't need to contend
with program memory paging. Avoiding this is a big help in getting started using PICI6s.

Locating tables of data in program memory requires a little thought. Accessing a table requires
the use of a computed address, so the table should not cross the boundary of a 256-location seg-
ment of program memory because the PCLATH bits(s) are involved. To keep things simple,
tables should be located in the first 256 program memory locations at this stage of your learning
process. The details are described in "Plein Up The Pace".

For computed addresses which involve PCH, the bits come from PCLATH.

PCH PCl
12 11 10 9 8 7 o
ITTTTI
From PCLATH Computed Result

PCLATH comes up ---00000 on power-on reset, so you shouldn't have to be concerned after that
unless your program writes to PCLATH. Bits 4,3 must be 0 and 0 (bits provided to handle larger
program memory space but must be 00 to make the PIC 16F84 work properly).

Don't sweat these details for now. Their importance will come into focus after you have done
some programming examples.

14
STATUS REGISTER

7 6 5 4 3 2 o
POR- 00011 XXX
'---y---J

For File RegisterBank


Select - Not Used In
J Carry/Borrow Flag
ADDWFAndADDLW
Instructions
This Book.
Write 00 WhenWriting Digit Carry/Borrow Flag
To The Status Register. ADDWFAndADDLW
Instructions

ZeroFlag
o... ClearIf Not Zero
1 - Set If The Result Of An Arithmetic Or
Logic Operation Is Zero

PowerDownBit
o- By Execution Of SLEEP Instruction
1 - AfterPower-Up Or By CLRWDT
Instruction Execution

Time-OutBit
o=A WDTTimeoutHasOccured
1 - After Power-Up And By CLRWDTAnd
SLEEP Instructions

Bank Select (Ignore)

Care must be taken when reading the status register so as not to affect its contents. Using bit
instructions (BTFSS or BTFSC) will not affect the contents while using MOVF does affect the Z
flag.

Writing to the status register using BSF, BCF or MOVWF instructions will not affect the status
register in any way other than the write itself (ie. no flags are affected by the execution of the
instruction).

15
CIRCUIT FOR EXPERIMENTS

CIRCUIT FOR EXPERIMENTING WITH THE PIC16F84 AND PIC16C54

A circuit for experimenting with the PIC 16F84 and PIC16C54 is shown. It has all the compo-
nents required for most of the experiments in this book. Building it saves building one circuit
for each experiment.

Providing a ZIP socket for the microcontroller is a good idea because it will be inserted and
removed many times.

+5V

+5V 10K
Typical For
10K RA3, RA2.
Digital
1/0

External Clock
--- 1 RA2

2RA3
RA1 18

RAO 17
RA1,RAO

Source
> 3 RA4ffOCKI OSC1 16
+5V
4 MCLR OSC2 15 N.C.
PIC16F84

-,
5 Vss Or Vdd 14
PIC16C54 Decoupling 4MHz
6 RBO/INT RB7 13 Clock

0.1~fT
Oscillator
7 RB1 RB612

+5V RB511
- 8RB2 N.C.

10K -- 9RB3 RB410


100n
680n
Typical For
~

i
Reset RB 7 Through RB 1
----« INT Input

Note: A 7-Segment LED Display


May Be Substituted For The
Individual LED s For One Of
The Experiments

16
'84 ON A BOARD
As an alternative, a simple more general purpose circuit module may be assembled for use in all
of the experiments in this book. It includes a PIC16F84 (or PIC16C54) in a socket with clock
oscillator, reset, power supply decoupling capacitor, and port pullup resistors. These items are
required in or are common to all of the experiments. The pullup resistors are used in the experi-
ments primarily for the purpose of preventing unused inputs from floating. There are pullups on
port B built into the PIC16F84. I decided not to use them because they just add confusion to the
program examples and detract from explanation of the applications themselves. So if you
use the circuit module, remember to activate (via DIP switches) pullup resistors on all unused
port lines (input or output). You can save refinements for later.

I recommend connecting the port lines to a 16-pin DIP socket. A 16-conductor ribbon cable ter-
minated with 16-pin DIP plugs may then be used to connect the '84 on a board to a solderless
breadboard for doing the experiments. The wiring done on the solderless breadboard for each
experiment is minimal and chances are you won't want to preserve the specialized part of the cir-
cuit after you have done the experiment anyway (on to better things).

I would definitely consider use of a ZIF socket for the '84 to avoid bending or damaging the
pins.

The '84 on a board may also be used for the experiments in "Ple'n Up'n1.e J)aee".

t
+5V

10KPuliup

1RA2 RA1 18 ,.--------+----. Typical For All

--
13 Port Lines
2 RA3 RAO 17

3 RA4fTOCKI OSC1 16
+5V
4 MCLR OSC215 N.C.
PIC16F84
5 Vss Vdd 14
_I
+5V
---- 6 RBO/tNT

7 RB1
RB713

RB612
0.11·tf

DeCOUPlingT
4MHz
Clock
Oscillator

10K -- 8 RB2 RB511


1000
-- 9 RB3 RB410

Reset

l
17
As an example to illustrate how the '84 on a board could be used, let's assume that we want to
breadboard the circuit shown:

TESTCIRCUIT

+5VDC

PIC16F84 10K

RS RA

i
The experiment calls for an LED at a port B pin. A 680 ohm resistor and LED could be
installed in the solderless breadboard. The corresponding pullup resistor DIP switch on the '84
on a board should be in the open position (see drawing on page 19).
The experiment also calls for a pullup resistor and switch on a port A pin. We could use the
pullup resistor on the '84 on a board and connect the port A line to a second switch (for use in
the experiment) on the solderless breadboard.

18
'84ON A BOARD
+SVDC +5VDC

10K
10K Utilized
Not Utilized

DIP Switch DIP Switch


PIC16F84
Open Closed
RB

Via Ribbon
Cable

SOLDERLESS BREADBOARD

i
The '84 on a board is used in every experiment as-is. Pullup resistors are available and switeh-
selectable making life a little easier. The parts or connections specific to each experiment are
located on the solderless breadboard to make changes simple and easy.

19
CHOOSING DEVELOPMENT TOOLS

MPLAB/Windows vs. MPLAB/MS-DOS

MPLAB from Microchip is an integrated development environment (IDE) meaning the text edi-
tor, assembler (MPASM) and device programmer software (PICSTART Plus) are integrated into
one program which runs under Windows (3.1 or 95) on a PC. By opening one program,
MPLAB, all of these functions are available via clicking the mouse .

MPLAB is Microchip's primary development software and will be updated continuously.

MPASM is also available as a stand-alone program for use under MS-DOS. The DOS version is
no longer being updated by Microchip, but will be available in its current form for some time.

Both MPLAB and MPASM are available free of charge from Microchip. They can be down-
loaded from their Web site or obtained from the factory or a sales office.

MPLAB may be used in conjunction with most simple low-cost device programmers as a tool
for creating the assembler source code and the assembled .HEX file. It is then necessary to quit
MPLAB and use the programmer manufacturer's device programmer driver software to stuff the
.HEX file into a PIC 16.

CHOOSING A DEVICE PROGRAMMER

Selecting a programmer for PIC16 development is a personal choice based on the following cri-
teria:

• MS-DOS vs. Windows programmer control software.


• Range of parts which can be programmed.
• Support (level, long-term).
• Price.
Simple, inexpensive device programmers are available which run under MS-DOS and which
program either a single device (PIC16F84) or multiple devices (such as all of the 14-bit core
mid-range devices). Windows-based software may become available for these simple program-
mers . As product offerings are continually changing in this fast-paced market, I suggest you
contact the programmer manufacturers directly for the latest information. Sources are listed in
appendix A.

Note that some programmers are connected to the PC's parallel (printer) port and some are con-
nected to a serial port (usually COM2).

20
Microchip's PICSTART Plus will program their entire line of devices. Their intent is to contin-
ually provide software and firmware upgrades to keep it that way. Firmware? The PICSTART
Plus contains a PIC17 which converts information received from the PC's serial port to the
appropriate signals to program each device. Since these devices have differing requirements, the
code in the PIC17 must be updated to cover the requirements of new devices as they become
available. The PICSTART Plus is used to program a blank PIC17 using the updated code pro-
vided by Microchip (free on their Web site).

The PICSTART Plus operates under Wmdows (3.1 or 95) and is connected to one of the PC's
serial ports (usually COM2).

The control software for the PICSTART Plus is incorporated in MPLAB. MPLAB is bundled
with each PICSTART Plus.

21
USING AN ASSEMBLER

An assembler is a program which, in this case, runs on an mM compatible computer and con-
verts readable instructions contained in a text file to hexadecimal code understood by the
PIC16. The MPASM assembler from Microchip has lots of capabilities. The advantages of
using it are:

• It's free (obtainable from Microchip).


• Most people use it, i.e, most people speak MPASM.
• If you start out with it, you won't have to relearn anything as you expand your
capabilities.
• Since Microchip manufactures both the chips and the assembler, you know you are on
their path and not a side road. You won't get left in the dust in the future.
• The examples in Microchip's "Embedded Control Handbook" and in magazine articles
are, for the most part, in Microchip's assembler dialect - so why not go
mainstream?
• The error detection feature will be very helpful.

You will need only a small portion of the MPASM assembler's capabilities to get started. An
explanation follows:

SOURCE CODE FOR THE ASSEMBLER

Code for PIC16s may be created using a simple text editor. If you use an MS-DOS version of
MPASM, a simple text editor such as QEdit (designed for programmers), PC Text or EDLIN
(included in MS-DOS) may be used. Any simple text editor may be used as long as it generates
an ASCII file without additional formatting or printer control commands. They tend to confuse
the assembler.

A text editor is built in to MPLAB for use with the version of MPASM included in MPLAB
(which runs under Windows).

Specific information such as which PIC16 part the code is written for and where the program
starts in the chip's program memory plus the instructions and labels (mnemonic names for
addresses) are typed in a specific format so that the assembler program can fmd them.

A very simple example will be used to show how all this is done. First, the program teaches a
PICl6F84's port B that all eight port lines are output lines (as opposed to input lines). Then the
program makes the least significant four lines logic 1 (HI) and the most significant four lines
logic 0 (LO). Finally, the microcontroller sits in a loop. Defmitions for these terms follow.

The source code is easy to layout using a text editor.

22
Teach Port 8 All
Outputs

i=======PICT1.ASM===========================10/14/97==
list p=16f84
radix hex
;-----------------------------------------------------
i cpu equates (memory map)
portb equ Ox06
;-----------------------------------------------------
org OxOOO
i
start movlw OxOO iload W with OxOO
tris portb iCOpy W tristate, port B
,· outputs
movlw OxOf iload W with OxOF
movwf portb iload port B with contents
i of W
circle goto circle idone

end
i-----------------------------------------------------
iat blast time, select:
i memory unprotected
·
,
;
watchdog timer disabled (default is enabled)
standard crystal (using 4 MHz osc for test)
·
, power-up timer on
;=======================================================

Semicolon (;)
The semicolon (;) is a delimiter which tells the assembler to ignore everything following the
semicolon on that line of text. If the semicolon is the first character on a line, the whole line is
ignored by the assembler. This is useful for putting in your own symbols to divide the text into
sections visually (--------- or =======) or for putting in comments or notes to explain and docu-
ment the program.

On the line which begins with "start" in the example, the information following the semicolon
"load w with OxOO" explains what the MOVLW instruction is being used for.

23
Tabs
The tab capability of the text editor is used to arrange code in columns. The assembler expects
to find specific items in three columns. The three columns are used five ways, one way for the
header section, a second way for the equate section (defined later), a third way for org state-
ments, a fourth way for the program section, and a fifth way for the end statement.

Assembler
Directive
~
Header
list p=16f84
radix hex

This Is An Hex Address


Label Equate Or Number
r--A--.~~

Equates equ

Not This Is An
Used ORG Hex Address
~~~

Origin (ORG) org

Literal
Label Instruction Or Label
~~ r----A--....
Program

This Is
End
~
End end

24
The assembler program "reads" each text file line, ignores it if it begins with a semicolon, and
steps through the three columns. If it finds "EQU", "ORO", or "END" in the second column, it
treats that as an EQUATE, ORO, or END command. If it finds one of the PICl6F84 program
commands in the second column, the assembler creates machine language code in hexadecimal.

Tab position (i.e, 8th column vs 9th or 10th, etc.) is not critical. When the assembler sees a tab
(or a space does the same thing) as it moves from left to right along the line, it knows there is a
transition from one column to the next.

STYLE
As you look at source code examples (text code), you will see quite a range of styles in dividing
up the page, placement of comments, etc. Don't let this confuse you. It is just a matter of differ-
ing styles of the individuals who created the programs. It is what's in the three columns not
blanked out with the use of ;'s that counts.

list p=16f84
radix hex
portb equ Ox06
org OxOOO
start movlw OxOO
tris portb
movlw OxOf
movwf portb
circle goto circle
end

25
HEADERS
The information at the top of the source file is called a header.

;======PICT1.ASM================================10/14/97==
list p=16f84
radix hex
i----------------------------------------------------- - - - -

The line

list p=16f84

indicates which PIC16 part the program will be placed in. "List" is an assembler directive which
has a bunch of meanings depending on what follows it. This is the only way we will use the list
directive.

The line

radix hex

indicates that the numbering system is hexadecimal unless otherwise specified in a specific
instruction. "Radix" is an assembler directive.

For all examples in this book, it is assumed that a header similar to the the one shown above is
used.

LABELS
A label is a mnemonic symbolic name assigned to an address. "portb" means port B whose real
hexadecimal address is OX06 in the file register memory space in a PICI6F84. Labels are nice
because once assigned via an EQUATE statement equating the symbol with a hexadecimal phys-
ical address, you no longer have to remember port B is at Ox06. Just refer to it in your program
via the label "portb".

Labels are also assigned merely by putting them in the label column of the source file. This is
done when the address can be anywhere, i.e. it does not have to be related to something physical
such as a port with a specific address. Labels defined in this way are automatically assigned
addresses by the assembler. We don't need to know what they are.

26
The rules for defining labels are:

• All labels must start in the first position in column 1.

• Labels must begin with an alpha character or an underbar.

• Labels may contain alphanumeric characters, the underbar and the question mark.

• Labels may be up to 31 characters long (you will probably run into the next column
before you run out of characters).

• Labels are case sensitive by default.

The underbar ( _ ) is useful as a means of separating words because spaces are not allowed. An
example is temp_file.

EQUATES

An equate statement may serve to assign a label to a specific address in the PIC16 designated by
a hexadecimal number.

portb
r " :

equ
Tells Assembler
This Is An Equate

~~

Means Hexadecimal _I "- Hexadecimal Address


(File Register f6 At ax06)

Equates may also be used to assign names to numbers. For example, we can assign the name
"min" to bit 1 in a register labeled "flags" with two equates.

min equ 1 ;min = bit 1


flags equ OxOc ;flags = file register OxOc

27
In a program, we could have a line with says:

bsf flags,min iset bit 1 in file register OxOc

As the assembler assembles a program, it comes to a label and looks up its corresponding
address or number (not the reverse).

The Bit Set File (BSF) instruction sets a bit in a file register. Setting a bit makes it a "1".
Clearing a bit makes it a "0".

LITERALS

Literals are constants or numbers, usually hexadecimal numbers. Literals are defmed using the
MOVLW and some logic and arithmetic instructions which are detailed in the programming
chapter.

Instruction
/ - label / -

start movlw OxOO

\- Literal (Constant)
HexadecimalOxOO
For Th is Example

28
ORG

ORO stands for origin. ORO statements will be used for three purposes in this book.

• ORO defines the address where the program code starts.

.:
Tells Assembler This Is
An ORG Statement

org OxOOO

Hex Address OxOOO, The First


Program Memory Location

• ORO is used to establish the reset vector for the PIC16C54 (details later).

Tells Assembler This Is


An ORG Statement

;- Hex Address ox1 FF - The Reset


Vector Points To This Location

org Oxlff
goto start

InstrucliO\- Address Of First


Program Instruction

• ORO is used to establish the start of the interrupt service routine for the PIC16F84.

Tells Assemb ler This Is


An ORG Statement

.:
Hex Address Ox004 - The Start Of The
Interrupt Service Routine

org Ox004

First
Instruction
Goes Here

29
END
An END statement is used to tell the assembler it has reached the end of the program.

.:
Tells Assembler The
Program Ends Here

end

An END statement must be used to end a program.

PROGRAM FORMAT

All program examples in this book are assumed to have the following format even though the
header, equates and end are not shown:

Standard
Header

Equates

Program

End end

* Explained in destination designator section of programming chapter.


Remember, the first line is always the processor type designation and the last line is always the
END statement.

30
FILES USED BY THE ASSEMBLER

Your program source files created using a text editor must have a file name with the extension
.ASM. The file name for the first example in the book is PICT1.ASM. The assembler will only
assemble files with the .ASM extension.

FILES CREATED BY THE ASSEMBLER

The assembler will create two files from your source code file which will be of interest to you.
They will have file names the same as the source file except for the extensions.

.LST
.HEX

The file whose name has the extension .LST is the assembler-generated listing of your program.

MPASM 01.40 Released PICT1.ASM 10 -5-1997 12:25:37 PAGE 1

LOC OBJECT CODE LINE SOURCE TEXT


VALUE

00001 ;=======PICT1.ASM===========================10/1 0 /9 7==


00002 list p=16f84
00003 radix hex
00004 i----------------------------------- ------------ - --- -
. 0 0 0 05 cpu equates (memory map)
00000006 00006 portb equ 06
00007 ;-------------------------------------------- --~ - ----
0000 00008 org OxOOO
00009
0000 3000 00010 start movlw OxOO ;load w with OxOO
Warning[224]: Use of this instruction is not recommended.
0001 0066 00011 tris portb ;copy w tristate, port B
00012 outputs
0002 300F 00013 movlw OxOf ;load w with OxOF
0003 0086 00014 movwf portb ;load port B with contents
00015 of w
0004 2804 00016 circle goto circle ;done
00017
00018 end

31
MPASM 01.40 Released PICT1.ASM 10-5-1997 12:25:37 PAGE 2

SYMBOL TABLE
LABEL VALUE

16F84 00000001
circle 00000004
portb 00000006
start 00000000

MEMORY USAGE MAP ('X' = Used, '-' = Unused)

0000 : XXXXX----------- ---------------- ---------------- ----------------

All other memory blocks unused.

Program Memory Words Used: 5


Program Memory Words Free: 1019

Errors o
Warnings 1 reported, o suppressed
Messages o reported, o suppressed

Note: The warning message regarding the use of the TRIS instruction will be ignored in this book.

The file whose name has the extension .HEX is the hexadecimal object code which will be used by
the programmer to program the PIC16 chip.

:08000000003066000F3086009D
:020008000428CA
:OOOOOOOlFF

32
PREVENTING SOME GOTCHAS

More Than One Way To Skin A Cat

There may be two or more ways to accomplish creating various aspects of a program with an
assembler. Specifying the microcontroller type can be handled using a "list" instruction (as done
in this book) or via an assembler command line option (not used in this book). As an example,
the approach taken here is to use one way consistently. Hopefully, it is the easiest way.

UPPER/lower Case

Use of upper vs. lower case letters seems to be very inconsistent in the program listings I have
studied. Sometimes it is significant and sometimes it is not (labels are case sensitive for exam-
ple).

Instruction names and port designations (A vs. B) are upper case in the text in this book because
that format seems to be the norm. All text in the assembler program listings except comments
are lower case to make them less confusing to read and so that case sensitivity is not an issue.

33
USING THE MS-DOS BASED MPASM ASSEMBLER

We will assume that you have installed MPASM on your computer's hard drive with the driver
software for your device programmer in the same directory. We will also assume that you have
access to your text editor while working in that directory.

HOW TO ASSEMBLE A PROGRAM

Just to get the feel of how all this stuff works, you may want to type the example program on
page 23 using your text editor and assemble it.

• Type it exactly as shown so it will work. There will be plenty of opportunities to make
mistakes of your own later.
• Note that if the text is too wide, it will flow into the next line. The overflow will look
like a label to the assembler (example: ====== . = is an illegal character for
a label).
• Name the file PICfl.ASM.
• Assemble using MPASM. PICfl.ASM and MPASM must be in the same directory.
• Type MPASM.
• Press return.
• Wait.
• A list of files, etc. will appear.

Source File : I * .ASM


....
Processor Type : INone I Blinking Cursor

Error File Yes I


Cross Reference File No I
Listing File Yes I
Hex Dump Type INHXSM.HEX

Assemble To Object File No

34
Note that as you work with MPASM that many of the menu selections may be toggled using the
return key.

• Press return.
• All .ASM files are shown.
• Use arrow keys to select (highlight) PICTl.ASM.
• Press return.
• Observe that PICTl.ASM has been entered in the appropriate places automatically.

• Arrow down - highlight processor type.


• Press return.
Processor Type : 16F84

• Arrow down - highlight error file.

Error File : Yes

• Press return.

Error File No

35
• The result is:

• Press FlO to assemble.


• When assembly is complete, a list will appear on-screen showing how many errors
there are (hopefully 0) and where they are.
• Press any key to get out.
• When the assembler has finished, use the text editor to open the file PICfl.LST to see
what the assembler created. Errors will be noted if there are any.
• If you make mistakes, consider them as serving to create an opportunity to fmd out
what the error codes mean. They may be corrected by opening the .ASM text file
using the text editor. Then repeat the assembly process.

36
MPLAB OVERVIEW - GETTING STARTED

MPLAB is a large program with lots of whiz-bang features, so it would take a whole book to .
describe it completely. As with most computer programs these days, you will only need to know
a little bit to get started using it. That's next.

Microchip continually releases new versions of MPLAB. The following instructions will help
get you started if you are using v3.40 or later. MPLAB v4.00 is the current version as this is
being written. If significant changes are made to MPLAB, updates to the following instructions
will be posted on the Square 1 Electronics website (http://www.sq-1.com) .

USING MPLAB - GETTING STARTED

If you have had experience using a text editor, MPASM (MS-DOS version) and a device pro-
grammer to program the PIC16s, using MPLAB may seem a bit strange at first because of the
termin ology and because the look and feel of MPLAB is quite different. Once these things
become familiar, it will be easy to use. Having the text editor, MPASM, and PICSTART Plus (if
you use it) software open/accessible simultaneously and to be able to switch back and forth
quickly at will is nice.

We will assume the use of Windows 95 for the following example.

Open MPLAB by double -clicking the Microchip MPLAB icon. A menu bar will appear at the
top of the screen when the MPLAB is ready for use.

Toolbars

MPLAB has four toolbars, one of which is displayed at a time across the top of the screen below
the menu bar. There are lots of buttons, but you will not need to know about any of them to get
started.

The four tool bars are:

• Edit
• Debug
• Project
• User Defined
The default toolbar is the last one you used before shutting down the computer the last time you
used it. The button farthest to the left on all four toolbars is used to select the toolbar you want.

37
Position the cursor over the toolbar button second from the left end of the toolbar and then move
the cursor horizontally to the button at the far left and leave it there. Notice that "swap toolbar"
appears in the gray stripe at the lower left corner of the screen. Moving the cursor from mid-
screen directly to the swap toolbar button does not always cause "swap toolbar" to appear (for
whatever reason). Moving the cursor across the toolbar a button at a time will allow you to see
the button functions displayed at the lower left corner of the screen. Click on the "swap toolbar"
button to look at the other toolbars. The toolbar names appear at the lower right corner of the
screen in the status bar.

Select the Debug toolbar. We won't be using the toolbar buttons, but the Debug toolbar must be
selected to allow PICSTART Plus to work (may be true for other programmers as well). The
debug toolbar is now the default toolbar (unless/until you select another one for some reason).

Select Development Mode And Device Type

Click "Options" in the menu bar. Click "Development Mode" in the drop-down list
(Options>Development Mode).

In the Development Mode dialog box:

• Select MPLAB-SIM Simulator. ,


"Editor Only" won't work. In the MPSIM (tm) Simulator mode it is possible to
move freely back and forth between edit, assemble and the device programmer.
• Select Processor: "PIC16F84".
• Click "Reset".

Project

A principal new term you will need to know to use MPLAB is "project". A project is one or
more files grouped together and used to make code for a PIC16. The best way to learn this stuff
is by doing a simple example.

Click "Project" in the menu bar. Click "New Project" in the drop-down list (Projects-New
Project).

In the New Project dialog box:

• Select a directory for the new project (click on "MPLAB" to highlight it).
• Type the file name.

PICTl.PIT
"-y--J '-yJ
l - means project
L your project name

• Click "OK".

The Edit Project dialog box will appear. In the box you will see a Project Files window with the
name of your file (with the extension .hex) displayed.

• Click on your file name to highlight (select) it.

38
Another term used in MPLAB is "node" which means a file associated with a project.

The Node Properties button is now active (black).

• Click on the Node Properties button.


The Node Properties dialog box will appear. We will use the default settings.

• Click "OK".

It may seem like going to the Node Properties box was a waste. Things won't go well if you
skip this step!

The Edit Project dialog box is now back on the screen.

• Click "OK".

Text Editor

A text editor is built into MPLAB.

In the file menu, click "New". A window labeled "Untitled" will appear.

Now you can type in some sample code. We will use PICTI.ASM from page 23. When you are
finished, save the file (Filec-Save).

In the "Save File" dialog box, edit the file name. Use the .ASM extension (PICTl.ASM).

• Click "OK".

Edit Project

Part of the process of editing a project assigns a source code file to a project. In the Project
menu, select "Edit Project" (Project-Edit Project).

The Edit Project dialog box will appear.

• Click on the Add Node button.

The object is to assign our file to the project. Project file names appear in a window. Find
PICTl.ASM and select it (click on file name). Click "OK". The project now has a source file
assigned to it.

The Edit Project dialog box is on-screen again. The file name PICTI.ASM appears in the win-
dow.

• Click "OK".

39
Assembler

To assemble your source code (with your project open and the source code on screen), click
"Make Project" under the project menu (Project>Make Project). The terminology is a bit
strange. Clicking "Make Project" causes the source code to be assembled by MPASM which is
built into MPLAB. The result is a file with your file name and the extension .HEX.

The assembly process ends with the Build Results window being displayed. If your code assem-
bles properly, the message "Build completed successfully" will appear. If there are errors or
warnings, each error or warning in the list will have a source code line number associated with
it. If you open the source code window's drop down list, you will see that the last item on the
list is "Toggle line numbers". Clicking on this will cause line numbers to appear in the left mar-
gin of the source code. Clicking again causes the line numbers to go away.

Ignore the three warning messages associated with this code example concerning processor type,
radix, and use of the TRIS instruction. The processor type is also specified as a selection in the
Development Mode dialog box (takes precedence over the source code). The radix is also speci-
fied via the default setting in the Node Properties dialog box (which takes precedence over the
source code).
Last, save your project via Project>Save Project. Then close your project via Project>Close
Project. Close MPLAB.

MORE MPLAB OPERATIONS

To View And Print A .LST File

In the file menu, select "View". A dialog box will appear. Type in the name of the file you
would like to view and print (example: PICTl.LST). Click "OK". The file will appear on
screen. To print the file, select "Print" in the file menu.

To Delete A Project

Delete the project files using Windows Explorer. It is the only way it can be done.

40
PROGRAMMING A DEVICE

By now you have had an opportunity to assemble the source code file PICTl.ASM and are ready
to proceed with programming the .HEX file created by MPASM into a PIC16F84 device.

MS-DOS BASED MPASM

Follow the instructions which came with your programmer. The file PICTl.HEX created by
MPASM and the device programmer driver software should be in the same directory on your
hard drive so the driver can find the .HEX file.

MPLAB

The "make project" process in MPLAB creates a .HEX file (PICT1.HEX in this case). If you
have a PICSTART Plus, the device programming instructions follow. If you have another pro-
grammer, you may need to close the MPLAB program and open the driver software for the
device programmer. The driver software and the .HEX file should be in the same directory.
Follow the device programmer manufacturer's instructions.

USING PICSTART PLUS

Begin by opening your existing project in MPLAB. Choose "Open Project" in the project menu
followed by selecting your project by name (pICTl.PJT). Choose "Open Source" in the file
menu and select "PICTl.ASM".

To Enable PICSTART Plus

Click on PICSTART PLUS in menu bar.


Click "Enable Programmer" on drop down list.
Programmer status dialog box.
Select device type.
Some items will be enabled (black)or grayed out depending on device type selected.
Voltages cannot be changed with PICSTART Plus programmer.
Set configuration bits by clicking on arrows (or do it in MPASM via _Config directive).
Ignore items where arrows are grey.
Ignore ill and voltages.

41
To ProgramNerify A Device

With "Programmer Status" dialogue box open:


Click "PICSTART PLUS" on menu bar.
Click "Program/Verify".
Program/Verify dialog box.
Un-check "program/verify ID's" and "EEPROM data" if not applicable.
Click "Program" button.
Message will appear if device not blank.
Programmer status will be displayed in text on same line as "Start Address" -
"Programming" (in process), "Success" or "Failure".

To Read A Device

With "Programmer Status" window open:


Click "PICSTART PLUS" on menu bar.
Click "Read Device".

THE BIG TEST!

Insert the programmed PIC 16F84 into the socket on your test board (power off!). Power up the
test board. The LEDs connected to port B should be off/on as follows:

Bit 7 6 5 4 3 2 1 0
Status 0 0 0 0 1 1 1 1

Controlling LEDs is a BIG DEAL at this point! You now know how to use the computer, text
editor, assembler, device programmer and program a microcontroller. Wow! Time to celebrate
I'd say.

42
WRITING PROGRAMS

PROGRAMMING CONCEPTS

The PIC16F84 microcontroller will respond to a series of coded instructions stored in program
memory.

When a designer (which may be you) thinks of something which he or she would like to control,
the natural thing to do is to think through the control process in logical steps. Creating a flow
chart is a good way to visualize these steps. The control process might consist of sensing
outside world events such as light vs. darkness, cows passing through a gate, temperature, a key
stroke etc., testing the data which has come from the sensors followed by taking one of two
possible program paths (branching) based on the test results, and controlling some outside
device such as a digital display, indicator light, motor, heater, etc.

Instructions for repetitive operations can be repeated in long strings, but that wastes valuable
memory space. It may even result in a program which is too long to fit in the available memory
space. Instead, one sequence of instructions can be used over and over in a loop and the
microcontroller goes 'round and 'round until something forces it to stop.

• Loops can go around forever or until the plug is pulled or an anvil is dropped on the
microcontroller chip.

• Or until a counter counts up to a predetermined number or down to O.

• Or until a test result says to move on.

43
An example of the use of a loop is a program used to read an input port and display the data
received (or the status of the lines) at an output port.

Loops are useful when it is necessary to perform an operation a certain number of times (n).

Load Counter with 0


Initialize

Do

Increment

44
The use of a loop prevents having to write the code n times and the requirement for memory
space to store it.

Another technique for keeping programs short and manageable is the use of subroutines. If the
same task is to be performed in two or more places in a program, the code can be written once
and stored in one location. When the points in the program are reached where the subroutine is
to be used (called), a CALL instruction is used. The last instruction in a subroutine is always a
return from subroutine (RETURN or RETLW) instruction. The program then continues where it
left off.

An important concept to keep in mind when using micros is that they can only do one thing at a
time, one very simple thing. They execute many very simple instructions and they do it
blindingly fast. The PICl6F84 executes roughly a million instructions every second with a
4MHz clock oscillator.

In situations where events of interest to the micro occur only once in a while, perhaps randomly,
it may be desirable to use a micro feature called the interrupt. In simplified form, if an event
occurs in the outside world which demands the micro's attention, the sensor monitoring the event
can be wired to direct a signal (pulse) to an interrupt line (pin) on the microcontroller. When the
signal arrives, the microcontroller drops what it was doing (after finishing the instruction it was
executing), and then jumps to a special program called an interrupt service routine. The purpose
of the routine is to do whatever the designer/programmer thinks is required when the outside
event occurs.

Micros do only one thing at a time, but they can be instructed to drop one task, take care of
another, and resume the original task.

Interrupts are a special area closely tied to the hardware used to make their occurance known, so
they will be discussed in detail in the interrupt section of this manual.

Finally another basic concept is that there is no way to write directly to a memory location or to
an I/O Port. Data must be put into the W register and then the W register contents must be
stored in the final location. A MOVLW or MOVF instruction loads the W register. A MOVWF
instruction stores a copy of the W register contents in a data memory location (file register)
leaving the contents of the W register unaltered.

PROGRAMMING EXAMPLES

The best way to learn how micros are used is to think of applications and write programs to
implement them. In this section, we will start out with very simple programs to demonstrate the
concepts we have just discussed. By the time you have finished this section, you will be able to
think in micro terms and will see micro applications in your work or hobbies. You will also be
able to visualize the methods for implementing micro solutions.

Simple programs used as examples will illustrate the use of the various types of instructions.

45
INSTRUCTION SET

The PICI6F84 microcontroller officially has 35 instructions in its instruction set. We will
temporarily use two obsolete instructions because it makes life much simpler (total 37
instructions to get started). The instruction set is presented categorized by type of operation.

The use of k, f, d, etc. will be explained later.

PIC16 instruction words used by the chip itself contain both the binary code for the instruction
and the binary address or some constant data. For the PICI6F84, instruction words are 14 bits
wide. How these words are constructed is described in the Microchip data book. I have found
that you simply won't need to know how this is done . Getting the assembly language
instructions and designators (d) correct should be the focus.

Move or Define Data


MOVLW k Loads W with literal.

MOVF f,d Moves copy of selected register contents into W or f.

MOVWF f Moves copy of W contents into selected register.

Change Register Contents


CLRF f Clears selected register to O.

CLRW Clears W register to O.

COMF f,d Complements selected register.


All 1's to O's, all O's to 1's
Result in W or f.

DECF f,d Decrements selected register.


Decrementing when contents of register is OXOO results in
0xFF. Result in W or f.

INCF f,d Increments selected register.


Incrementing when contents of register is 0xFF results in
OxOO. Result in W or f.
BCF f,b Clears selected bit in selected register to O.

BSF f,b Sets selected bit in selected register to 1.

RLF f,d Rotates bits in selected register one position to the left.
Bits rotate through carry flag.
Result in W or f.

RRF f,d Rotates bits in selected register one position to the right.
Bits rotate through carry flag.
Result in W or f.

46
SWAPF f,d Exchanges MS and LS nibbles of selected register.
Result in W or f.

Control Program Flow


OOTO k 00 to specified address.
CALL k Call subroutine at specified starting address.

RETURN Return from subroutine.

RETLW k Return from subroutine. Loads W with literal.

RETFIE Return from interrupt.

BTFSC f,b Tests specified bit in specified register.


Skips the next instruction if bit tested is clear (0).

BTFSS f,b Tests specified bit in specified register.


Skips the next instruction if bit tested is set (1).

DECFSZ f,d Decrements specified register. Skips next instruction if


register contents = O.
Destination W or f.

INCFSZ f,d Increments specified register. Skips next instruction if


register contents = O.
Destination W or f.

Nothing
NOP Do nothing for one instruction cycle (time delay, save room
for future code mods, debugging = break).

Control Microcontroller
CLRWDT Clear watchdog timer (reset to zero). Also resets the prescaler
of the watchdog timer. Status bits TO and PD are set.

OPTION W contents (bit pattern) sent to option register to control


prescaler ratio, real time clock trigger edge, and real
time counter/clock source.

SLEEP Puts microcontroller to sleep to reduce power consumption.


Wakeup via reset, watchdog timer, or external
real time input.

TRIS f W bit pattern determines port line input vs. output


on line-by-line basis for selected port.

47
Logic

ANDLW k AND's contents of W with literal (mask) contained in instruction.


Result in W.

ANDWF f,d AND's contents of W with contents of selected register.


Result in W or f.

IORLW k OR's contents ofW with literal (mask) contained in instruction.


Result in W.

IORWF f,d OR's contents of W with contents of selected register.


Result in W or f.

XORLW k XOR's contents of W with literal (mask) contained in instruction.


Result in W.

XORWF f,d XOR's contents of W with contents of selected register.


Result in W or f.

Arithmetic

ADDWF f,d Adds contents of W to contents of selected register.


Result in W or f.

ADDLW · k Add literal to W. Result in W.

SUBLW k Subtract W from literal. Result in W. (NOT subtract


literal from Was name indicates!).

SUBWF f,d Subtracts contents ofW from contents of selected


register by 2's complement arithmetic. Result
in Worf.

WEIRD MOVE INSTRUCTION

Referring to:

MOVF f,d Moves copy of selected register contents into W or f.

MOVF f,w makes sense (i.e, move the contents of a file register into the W register). MOVF
f,f (moving the contents of a file register out and putting it back in) doesn't make sense except
that it can be used as a method for testing the Zero (Z) flag. The Z flag is affected by the MOVF
instruction. This will make more sense to you later.

You can think of the MOVF instruction as meaning MOVFW (move the contents of a file
register to the W register). MOVFW is not a legal op code but the version of MPLAB I use
accepts it. If you choose to use the illegal op code, MOVFW moves data one way and MOVWF
moves it the other way making remembering the op codes a lot easier. Test this with the version
of MPLAB you use to be sure it works for you.

48
INSTRUCTION FORMAT FOR ASSEMBLER

First, some definitions:

f = file register
d = destination
o= W register
1 = file register
k = constant (literal) (literal instructions) .
k = address label (call or goto instructions)
b = bit designator (bit-oriented instructions)
b = binary (literal instructions)
d = decimal (literal instructions)

There are four categories of instructions when it comes to formatting instructions for the
assembler.

Byte-Oriented Instructions

File Register Designator


Hex Address (2-Digit) or
Label Specifies Which
File Register Is To Be Used
By Instruction

Instruction

Destination Designator
Specifies Where Result Of
Operation Is To Be Placed

d = 0 W Register
d = 1 File Register

49
Bit-Oriented Instructions

File RegIster DesIgnator


Hex Address (2-Digit) or
Label Specifies Which
File Register Is To Be Used
By Instruction

Instruction

BIt DesIgnator
Hex O~ 70r
Label (Defined By Equate)

Literal Instructions

LIteral = Constant
Uterals:
Hexadecimal OxOf
Binary b'00001111 '
Decimal d'16'

Instruction

Control Instructions (CALL and GOTO)

___Ik
r Addr••• L.b.1

Instruction

50
DESTINATION DESIGNATOR (d)

Byte-oriented instructions are accompanied by a designation designator referred to as "d".

d =0 Destination is W register (result in W).


d=1 Destination is a file register (result in f).

Trying to remember if d should be 0 or 1 is a nuisance. MPLAB takes care of this for you as
you can use w and f in the source code and MPLAB knows that for w d=O and that for f d=l.
The MS-DOS version of MPLAB does NOT take care of this automatically. The solution is to
put the following equates at the beginning of every program:

w equ 0
f equ 1

Examples:

decf counter,f if means result in file


,. register
movf counter,w iW means result in w register

Note that if the contents of a file register are operated on and the destination of the result is W,
the contents of the file register remain unchanged.

incf value,w iresult to W


rrf value,w iresult to W

In both cases, the result goes to Wand the contents of the file register labeled "value" are
unchanged.

The examples of complete programs in this book assume the use of MPLAB and the w and f
equates are not shown. If you are using an MS-DOS version ofMPASM, you will need to
remember to add them to your source code.

51
HEXADECIMAL NUMBERS vs. MPASM ASSEMBLER

The use of hexadecimal numbers with PIC16s is full of inconsistencies! You will see this when
you look through program listings from other sources. For example port B may be equated to
the file address hexadecimal 06 in the following ways:

portb equ 6
06
06h
h'06'
Ox06

The MOVLW instruction is used to load the W register with hexadecimal literals as follows :

movlw 00
OOh
h' 00'
OxOO
Of
ff won't work
ffh won't work
h'ff'
Oxff

If 00 and Ofwork, why doesn't ff work? It looks like the same form to me. The important thing
is to be aware of the inconsistencies and use a format that always works.

The first character in the literal expression must be "0" or "h" for the assembler to work.

Sooooo to make things manageable we will settle on a standard/uniform way of doing


things for the examples in this book.

Single hex digits by themselves will be used for:

Equates bits 0 ~ 7
Instructions bit designator b 0 ~ 7

Hex addresses will be in the following form:

File registers = data memory OxXX


Program memory OxXXX

52
Hex numbers in literal instructions will be in the following form:

~
r
r-L-,
OxXX
2 Hex Digits

I Think Of This As SignRying Hex

movlw OxOf
'-r'y

Signffies Hex ~ ' - OF Hex

The programs in this book are written using these conventions.

All references to hexadecimal numbers in the text of the book will use the Ox notation.

BINARY AND DECIMAL NUMBERS vs. MPASM ASSEMBLER

Binary and decimal literals may be written as shown:

movlw b'OOOOllll' ibinary


movlw d'16' idecimal

Note that the' is the apostrophe on the same key as " on the keyboard. Some listings I have seen
appear to have the literal bracketed in' '. Only' works with MPASM.
I

ASCII CHARACTERS vs. MPASM ASSEMBLER

Most ASCII characters may be included in a program by doing one of the following:

movlw a'C' iascii capital C


or simply

movlw 'C' iascii capital C

53
ADDRESSING MODES

• IMMEDIATE - using "literal" instruction which loads data from program memory into
Wregister.

• DIRECT - specific address.

• INDIRECf - using file select register (FSR) (f4).

• RELATIVE
via bit test and skip (2 addresses away).
via loading computed addresses into the program counter. Could be out into the
middle of a bunch of RETLWs (lookup table) or GaTOs (jump table).

Immediate Addressing

The literal instruction has the data (literal) built into the instruction word.

Direct Addressing

The direct addressing mode is straightforward. The address is specified following the
instruction.

clrf temp ;clear file labeled temp

G;direCI Addressing
T~fi;~'tfileregIsterfO (indirect address or indirect file, INDF) at address OxOO is not physically
implemented (it ain't there!). Using OxOO as an address actually calls for the contents of the file
select register f4 (FSR at Ox04) to be used as the address of a file register. The indirect address
register is bogus. Using its address tells the PIC16 that what you really want is the address
pointed to by the FSR. Weird, but that's how it works.

If you want to take off relative to a known file register address, add an offset or index to that
address, store the result in the FSR and use OxOO as the file register designator for the instruction
which takes you to the resulting address. This is like "indexed addressing" with other
microcontrollers. Since there are only 68 general-purpose file registers in a PIC16F84, you
won 't be indexing far.

54
; assume address is in file labeled "hold"

movf hold,w ;contents of hold (address) to W


movwf fsr ;W to fsr
movf OxOO,w ;load data at address into W
; continue
To review. using OXOO (the address of fO) causes the contents of the FSR (at Ox04) to be
substituted and used as the file register address of the instruction. FOis useful as an address
pointer. .

A practical application for this might be sending characters from 16 file registers Ox20 to Ox2F
to an LCD display.

movlw Ox20 ;initialize pointer


movwf fsr
next movf indf,w ;get data pointed to
call send ;sub sends byte to LCD
incf fsr,f ;inc pointer
btfss fsr,4 ;done ?
goto next ;no, again

To implement this. one could load the "display RAM" in advance using MOVLW instructions.

Relative Addressing

Relative addressing for the PIC16 involves altering the contents of the program counter. This
constitutes a computed jump from wherever the program counter is to some address relative to
that point

For OOTO and CALL instructions on the PIC16F84. this is handled automatically because the
address is included in the instruction.

The 5 high bits of the PC are loaded from PC latch high (PCLATH) by any instruction which
writes to the PC. All computed jumps must be preceded by being sure that PCLATH contains
the correct bits. Since we are avoiding program memory paging for now. we are limited to using
the first 256 locations of program memory for computed jumps.

So. if you want to take off from where the PC is. add the offset or index to the PC and execution
will continue at the resulting address. Use the contents of a file register as an offset or index to
jump to a code chunk:or to a OOTO.

55
Use Of The RETLW Instruction For Accessing Tables of Data Via Relative
Addressing

The RETLW instruction causes the W register to be loaded with the literal value following the
RETLW instruction. This is useful for implementing data tables in program memory. Limited
amounts of data can be stored in program memory and accessed this way.

As an example, let's say we have an application where a counter (file register) is incremented (0
to some number = 9 or less) and we want to display the result on a 7-segment LED display.
Seven segment codes are stored as a table in program memory with each code attached to a
RETLW instruction (coupled with RETLW instructions). This is a way to store 8-bit data in 14-
bit program memory and gain access to it.

The code which must access the table calls the subroutine which contains the table. The counter
is labeled "count". After the counter has been incremented the last time, the counter contents are
loaded in Wand the subroutine is called. The first instruction in the subroutine adds the
contents ofW to the program counter (used as an index or offset). Execution jumps to a
RETLW instruction containing the 7-segment code corresponding to the counter contents.
Execution returns to the main program and the W register now contains the 7-segment code.
The code is then sent to the 7-segment display via port B.

The details for this example follow at the end of the programming chapter.

56
ADDWF

RETLW
RETLW
RETLW
Return From Subroutine RETLW
Table

RETLW

"
Move Data Returned To
Port B For Display

pc equ Ox02 iprogram counter


count equ OxOC icounter

movf count,w icounter contents to w


call segments icall sub
movwf portb idisplay results

segments addwf pc,f iadd offset to pgm ctr


retlw Ox3f iO seven-segment
retlw Ox06 i1
retlw Ox53 i2
retlw Ox4f i3
retlw Ox66 i4
retlw Ox6d i5
retlw Ox7d i6
retlw Ox07 i7
retlw Ox7f i8
retlw Ox6f i9

57
USING THE PORTS

Port Data Direction

Port data direction (input vs. output) is controlled using a special register called the tristate
register. Like the option register, we will think of the tristate (1RIS) register as a "buried"
register, not part of the file register address space and having no address. We will use the TRIS
instruction to write to it. This is the second of two obsolete PICI6F84 instructions which we
will use because it makes life more manageable. File register bank switching and the use of
Microchip's intended methods will come later.

The TRIS and OPTION methods are the only ones available for the PICI6C54, so learning them
now is part of the backward compatibility plan.

The TRIS register has 8 bits.

7 o
TRIS Register o=TTI,---,-----,------,-----,

Loading a "0" in a TRIS register bit makes the corresponding port bit an output. Conversely, a
"1" results in an input.

movlw b'00001111' iteach port B


tris portb ibits7,6,5,4 outputs
,. bits 3,2,1,0 inputs

The TRIS instruction transfers the contents of the W register into the TRIS register which selects
port data direction.

Port ReadlWrite

An input port may be read as a whole by using the MOVF portX, W instruction. Data is valid as
of the instant the port is read. An individual port line may be read using the BTFSC or BTFSS
instructions.

58
The bit-oriented instructions BCF and BSF read the whole port contents into an internal central
processing unit (CPU) register, change a bit, and write the contents of the internal CPU register
back to the port. This is called read-modify-write.

The port is read at the beginning of an instruction cycle and written to at the end of the
instruction cycle. If a read immediately follows a write to the same port, problems may occur.
Time should be allowed for the port to stabilize. Inserting a NOP instruction between the write
and read should prevent this problem from occurring.

Doing two consecutive writes to a port may cause the same problem to occur. Again, inserting a
NOP should prevent trouble.

FLAGS

A flag is a one-bit register which is set (1) or cleared (0) by execution of one or more types of
instructions. The setting or clearing generally takes place automatically. After execution of an
instruction, the affected flag may be tested to see if it was set or cleared. The path taken by the
program depends on the status of the flag being tested.

There are three flags in the PICI6F84. We will be interested in two of them (Z and C). For
now, it is sufficient to know that these flags exist in the status word register S. Their
significance will be discussed as the applications for them arise.

FLAGS

Z Zero
C Carry

SIMPLE DATA TRANSFERS

This program moves data from port B (file register f6 at address Ox06) to a file register labeled
"hold".

movf portb,w iffiove contents of port B to W reg


ffiovwf hold iffiove contents of W register to
ifile register labeled hold

This requires moving data via the W register. There is no direct way to move data from one file
register to another.

59
A data transfer is used to send a bit pattern to an output port. Let's arbitrarily choose the
following bit pattern and send it to the parallel output port B located at Ox06 which we will
assume drives 8 LEDs.

Bit Pattern 0000 1111


Hexadecimal OxO OxF

movlw OxOO iload W with OxOO


tris portb iteach port B outputs
movlw OxOf iload W with OxOF
movwf portb iload port B with contents of W

To set an output port to all O's as part of a program, you can use the CLRF instruction which
clears the selected register to OxOO.

clrf portb

Input ports are read using data transfers. DIP switches are assumed to be located at port A, bits
3,2, 1,0 (LO 4 bits) and LEDs are assumed to be located at port B.

i=======PICT2.ASM==============================5/19/96==
idata transfer demo
i----------------------------------------------------- - -
list p=16f84
radix hex
;-------------------------------------------------------
·
,
porta
cpu equates (memory map)
equ OxOS
portb equ Ox06
i----------------------------------------------------- - -
org OxOOO
start movlw Oxff iload w with OxFF
tris porta iCOPY w tristate, port A
i inputs
movlw OxOO iload w with OxOO
tris portb iCOPY w tristate, port B
·
,
movf
outputs
porta,w iread port A, result in W
movwf portb iswitch status display at port B
circle goto circle icircle

end
i----------------------------------------------------- - -
iat blast time, select:
·
, memory unprotected
·
, watchdog timer disabled (default is enabled)
standard crystal (using 4 MHz osc for test)
i
·
, power-up timer on
;=======================================================

60
Set the switches at the input port and run the program. Compare the resulting bit pattern at the
display with the pattern you set in. Change the input pattern and rerun the program.

LOOP· ENDLESS
Above we used an endless loop to fake a halt (the PIC 16F84 does not have a halt instruction).
The GOTO (go to) instruction goes to the location labeled "circle" which is the address of the
GOTO instruction. The PIC16F84 sits in an endless loop (circle).

Next we will use the GOTO instruction to make a more useful loop. The program will read the
input port A and display the 4 bits of port A continuously at the lowest 4 bits of port B. This
time, the program repeats over and over by jumping back to "start" each trip through the loop.
The code is the same as before except for the address in the GOTO instruction.

The program is the same as above except for the line beginning with the label "circle" is
replaced with:

gata start iagain

Now vary the switch settings while the program is running.

This loop will run forever unless you press the reset switch or pull the plug (sometimes called
"absolute reset").

61
LOOP WITH COUNTER

It is often necessary to perform some operation a specified number of times. To do this, a file
register may be set aside to be used as a counter. Each time the operation is performed, a one is
added to the counter. This is called incrementing the counter and the instruction is INeE When
the number in the counter becomes equal to the number of times the operation is to be
performed, the program can stop or go on to something else. A simple example will illustrate
this concept.

Load Counter With OxOO Initialize


Again

Move Counter Contents


To Port 8 Do

Add 1

We will use file register fc (general purpose file register = RAM) labeled "count" as the counter.
Storing the counter contents at port B is just something for the program to do. We will find
more exciting things to do later in this section.

; =======PICT3.ASM==============================5/22/96==
;loop with counter demo
; count up
,--------------------------------------------------------
list p=16f84
radix hex
i----------------------------------------------------- - -
; cpu equates (memory map)
status equ Ox03
portb equ Ox06
count equ OxOc
i----------------------------------------------------- - -
org OxOOO
start movlw OxOO ;load w with OxOO

tris portb ;copy w tristate, port B


; outputs
clrf portb ;outputs LO
clrf count ;clear counter

62
again movf count,w ;counter contents to W
movwf portb ;counter contents to port B
incf count,f ;inc count, result in count
movlw Ox05 ; load w with Ox05
subwf count,w ;subtract Ox 05 from counter,
,. result in W register
btfs s status,2;test Z flag
goto aga in ;not = Ox05
c i r cle g ot o circ le ; = Ox 05, done
;
end
; --------- --- - ---- -------- ------ ------------------------
;at b la s t t ime, s el e ct:
.
, memo r y unprotecte d
.
, wat c h d o g t i me r di s abl e d (de fa ult is enabled)
; standard c r y s t a l (using 4 MHz osc for test)
; power-up timer on
i===== === = = = = = = == = = = = = = = = = = = === = = = = = = ========== = = ===== ==

Port B will indicate Ox04 in binary (00000100).

This program illustrates a very important concept, the power of microcontrollers to make
decisi ons. A comparison is made using the MOVLW and SUBWF instructions to see if two
things are the same. If they are, the program stops. If not, the program loop continues until the
counter hits the number we have chosen . The subtraction and bit test instructions (comparison)
determine the flow or path of the program.

Load the program and run it to see what happens . It will be finished in a few microseconds.
Port B should contain Ox04. You may want to try other numbers in the counter.

You may find it easier to load the counter with the number of times an operation is to be
performed and decrement the counter using the DECFSZ instruction. When the count falls to
zero, the next instruction (a GOTO) is skipped sending execution to the code following.

The previous and following examples send the counter contents to LEDs at port B 5 times.
When incrementing, the counter contents are 0 when the first operation occurs and 4 when the
last one occurs. When decrementing, the counter contents are 5 when the first operation occurs
and 1 when the last operation occurs. •

63
Load Counter With No. Initialize

Again

Move Counter Contents


To Port B Do

Subtract 1

DECFSZ Instruction

Done (Circle)

i=======PICT22.ASM=============================2/16/99==
ilOOP with counter demo
i count down
i----------------------------------------------------- - -
list p=16f84
radix hex
i----------------------------------------------------- - -
i cpu equates (memory map)
portb equ Ox06
count equ OxOc
i----------------------------------------------------- - -
org OxOOO
start movlw OxOO iload w with OxOO
tris portb iCOpy w tristate, port B outputs
clrf portb iport B lines low
movlw OxOS iload w with OxOS
movwf count iW contents to counter
again movf count,w icounter contents into W
movwf portb idisplay at port B
decfsz count,f r dec counter, result in count
goto again icount not = OxOO
circle goto circle icount = OxOO, done
iOxOl at port B
,.
end

64
;-------------------------------------------------------
;at blast time, select:
; memory unprotected
; watchdog timer disabled (default is enabled)
.
, standard crystal (using 4 MH z osc for test)
; power-up timer on
;=======================================================

Port B will indicate OxOI in binary (00000001) . This demo is boring, but it illustrates the
concept. This technique will be used in time delay loops later.
A key consideration in designing program loops using counters is what order to do things in.
The three things going on are doing whatever the loop is designed to do, incrementing or
decrementing the counter and testing the counter. If these operations are done in the wrong
order, the program will produce strange results.

LOOP UNTIL

Another use for a loop is a loop-until situation.

No

Yes

An example follows in the section on bit manipulation. The program goes into a loop until a
switch is opened.

65
COMPARISONS

The contents of the W register can be compared with a literal value N to determine their relative
magnitudes. This is done this by subtracting the contents of W from the literal value.

movlw OxXX iload W with literal


sublw N isubtract contents of W from
,. literal N - Result in W
btfsc/s status, 2 itest Z-flag, skip next instruction
if result 0/1
,.
i
goto

Result:

Zero flag is set if W = N


Zero flag is clear if W :# N

A branch may be taken or not depending on the results of the comparison.

Remember that the SUBLW instruction really subtracts W from the literal value.

A further result is:

Carry flag is set if W s N


Carry flag is clear if W > N

Possible tests are:

Test For Flag Tested

W = N Z Set
W :# N Z Clear
W s N C Set
W> N C Clear

Flags: Set = 1, Clear = 0

Follow the subtraction with "bit test, skip if' to send the microcontroller to whatever code is
appropriate depending on the results of the comparison.

Here is a simple program to demonstrate a method of testing the comparison procedure. LEOs
are assumed to be connected to port "B" for use as an indicator.

66
Load W With Test
Number

Status Register To
Port B LEO"s

2 1 0

=rzTTCJ
Status

---------------------------
N W Z C
---------------------------
W < N OxOS Ox04 0 1
W = N OxOS OxOS 1 1
W > N OxOS Ox06 0 0

;=======PICTS.ASM=============================10/12/97==
list p=16f84
radix hex
;-------------------------------------------------------
.
, cpu equates (memory map)
status equ 03
portb equ 06
;-------------------------------------------------------
org 0
;
start movlw OxOO ;load w with OxOO
tris portb ;copy w tristate, port B outputs
movlw Ox04 ;test number in w
sublw OxOS ;subtract W from N (OxOS)
movf status,w ;get status
movwf portb ;display status via LEDs
circle goto circle ; done
;
end
i--------------- -------------------------------------- - -

67
iat blast time, select:
i memory unprotected
i watchdog timer disabled (default is enabled)
standard crystal (using 4 MHz osc for test)
,.
i
power-up timer on
;=======================================================

Note that subtraction followed by a check to see if the carry flag is set tests for W "less than"
or "equal to" the literal value N. To test for W "less than" the literal N exclusively, use the
desired test number (N) minus one. M = N-l.

M-N -1

~---. W>M
No-Carry
SoW~N
Flag Clear

WsM
SoW<N

To test for W less than the literal N, use N minus 1 as the literal value for test purposes.

M=N-l
W ~ N C Set
W > N C Clear
To test for W<N:

Use N=OxOS
M=N-l = Ox04

W M C Means
--------------------- -------
Ox03 Ox04 Set W<N
Ox04 Ox04 Set W<N
OxOS Ox04 Clear W not <N

To review - test stuff by comparing an unknown with a known standard and branching to a set of
instructions located elsewhere if the test is affirmative.

68
Another way to test for two bytes being equal is to use the XORLW instruction. The byte to be
tested is XOR'd with a test byte. If they match, the Z-flag will be set (see bit manipulation using
logic instructions section).

A method of testing a byte in a file register to see if it is zero is to use the MOVF instruction and
place the result in the register it came from. The Z-flag is affected, so if it is set after the byte is
replaced, the register contains "0".

movf reg,f imove file, replace


btfss status, 2 iskip next if Z set
goto elsewhere
i continue

BIT MANIPULATION USING BIT MANIPULATION INSTRUCTIONS

The PIC16F84 has bit manipulation instructions which can be used to set, clear, or test an
individual bit or to test an individual bit. These instructions operate on the file registers.

Bit Set/Clear

Bit set (BSF) and bit clear (BCF) instructions operate on a selected bit in a selected register.

File Register Designator


Hex Address (2-Digit) or
LabelSpecifies Which
File Register Is To Be Used
By Instruction

Instruction

Bit Designator
Hex 0-+ 70r
Label (Defined By Equate)

As an example, bit 3 of port A can be set (made logic 1 or HI) by:

bsf porta, 3 iset port A, bit 3

69
Bit Testing

A bit in a file register may be tested using the B1FSC or B1FSS instruction.

File Register Designator


Hex Address (2-Digit) or
LabelSpecifies Which
File RegisterIs To Be Used
By Instruction

Instruction

Bit Designator
Hex o~ 70r
Label (Defined By Equate)

By way of example, we want to test bit 0 in the file register labeled "indicator" to see if it is clear
(0).

btfsc indicator, 0 ;test indicator bit 0


; skip next instruction
; if clear
goto elsewhere ;jump if set
,. continue

If the bit tested is clear, the next instruction is skipped. So the GOTO is a branch which will be
taken if bit 0 is set. Otherwise, code execution continues in sequence.

70
BIT MANIPULATION USING LOGIC INSTRUCTIONS

Logical operations and shifting bytes sideways may be used to change or test specific bits in a
file register or in the W register. These methods are useful when two or more bits in a byte must
be changed or tested in one instruction cycle.

Change Specific Bit To "1"

OR with an a-bit binary number which is all zeros except


the bit to be changed to a "1"
OR with "0" leaves bit unchanged
OR with "1" results in "1"

Change Specific Bit To "0"

AND with an a-bit binary number which is all ones except


the bit to be changed to a "0"
AND with "1" leaves bit unchanged
AND with "0" results in "0" (called masking)

Change Specific Bit To It's Complement

o to 1 and 1 to 0

XOR with an a-bit binary number which is all zeros except


the bit to be changed to its complement (Exclusive
OR) .
XOR with "1" changes bit to complement
XOR with "0" results in no change

Comparison· Test For Specific Byte

XOR with byte equal to the one you are looking for. If Z-flag
is set, they match. This is another comparison method to
be used when looking for identical bytes.

Test For "0"

OR with "0", then test the Z-flag. If the Z-flag is set, the
bytes match and the byte tested is "0".

71
We can try out the logic bit manipulation instructions by playing with bit 5 (arbitrary choice) in
the W register.

Make it a "1" with lOR 0010 0000

movlw b'OOOOOOOO'
iorlw b'00100000' ;make bit 5 a 1
movwf portb ;display at port b
circle goto circle ;circle

Make it a "0" with AND 1101 1111

movlw b'00100000'
andlw b'11011111' ;make bit 5 a 0
movwf portb ;display at port b
circle goto circle ;circle

Change it with XOR 0010 0000 (complement or


invert)

movlw b'OOOOOOOO'
xorlw b'00100000' ;complement bit 5
movwf portb ;display at port b
circle goto circle ;circle

Test for equal bytes

movlw b'01010101'
xorlw b'01010101'
movwf portb ;display at port b
circle goto circle ;circle

Test for "0"

movlw b'OOOOOOOO' ;test byte


iorlw b'OOOOOOOO' ;OR with "0"
movf status,w ;get status
movwf portb ;display ; status
circle goto circle ;circle

72
USING BIT MANIPULATION

Next we will try a program which uses bit manipulation. The objective of the program is to look
at an input port line and when it has a 1 on it, output a 1 on an output port line (if sense X, then
turn on Y). Bit 3 of port A is arbitrarily chosen as the input line to be sensed and bit 2 of port B
is arbitrarily chosen as the output line to be turned on. The input line switch is closed before the
program is run. The output port line is cleared to 0 at the beginning of the program so the LED
will be off when the program is initiated.

+5VDC

..to?"'" 10K

RA3

PIC16F84

RBO t----,
i
±SBon
I~

No

73
i=======PICTI0.ASM===============================6/25/96==
ibit manipulation demo
; -- ------------------------------------------- ----------- -
list p=16f84
radi x hex
i-- ---- ---- -------------------------------- -- ------ --- - - - -
i cpu equates (memory map)
porta equ Ox05
portb equ Ox06
;---------------------------------------------------------
org OxOOO
i
start movlw b'llllllll' iload W
tris porta iteach port A
movlw b'11111011' iload W
tris portb iteach port B
bcf portb,2 iturn off LED
switch btfss porta,3 ibit 3 HI?
goto switch ino
bsf portb,2 iyes, turn on LED
circle goto circle idone

end
i- ---------- ----- ------- --------- ---- ------- -------- -- - - - -
r at; blast time,select:
i memory unprotected
,· watchdog timer disabled (default is enabled)
i standard crystal (using 4 MHz osc for test)
,· power-up timer on
.
,-=========================================================

74
The next example program illustrates an application for bit manipulation in event counting.
Events represented by a series of switch closures can be counted. The example program will
count the number of times the bit 3 switch used in the previous example is opened allowing the
port A bit 3 input line to be pulled up to logic 1. The count is displayed in binary on LEDs
connected to port B.
+5VOC

10K

RA3

PIC16F84

RB7-0
i
6S0n

S LEOs 1f'
-

InitializeCounter To
CounterLabel.. "Count" OxOO

BTFSS

BTFSC

75
Start with switch closed, bit = O.

Loop 'til bit = 1 which means a transition from 0 to 1 has occurred (leading edge of pulse
detected).

Loop 'til bit = 0 which means a transition from 1 to 0 has occurred (trailing edge of pulse
detected).

The pulse is counted when the trailing edge has been detected.

Leading Edge
\ r Trailing Ed9"

-.I1 n n.

i=======PICTll.ASM===============================6/25/96==
ievent counting demo
i----------------------------------------------------- - - - -
list p=16f84
radix hex
i----------------------------------------------------- - - - -
i cpu equates (memory map)
porta equ Ox05
portb equ Ox06
count equ OxOc
,._--------------------------------------------------------
org OxOOO
i
start movlw Oxff
tris porta iteach port A inputs
movlw OxOO
tris portb iteach port B outputs
clrf portb iport B lines LO
clrf count iinitialize counter
i ?
h 1. btfss porta, 3 iport A, bit 3 HI?
goto i ?
h 1. ino
lo? btfsc porta, 3 iport A, bit 3 LO?
goto lo? ino
incf count,f iyes
movf count,w icounter contents to W
movwf portb idisplay counter contents
,. at port B
goto i ?
h 1. iagain
i
end
,. _- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

76
;at blast time, select:
,· memory unprotected
; watchdog timer disabled (default is enabled)
·
, standard crystal (using 4 MHz osc for test)
·
, power-up timer on
;=======================================================

SEQUENCING

The RLF (rotate file register contents left one bit) instruction can be used to shift data memory
contents left one bit position at a time. Each time the RLF instruction is executed, the byte is
shifted left one position, the left or most significant bit is moved to the carry flag, and the carry
flag contents is shifted into the file register's least significant bit.

Carry
Flag

The RRF instruction does the same thing, but in the opposite direction.

Sometimes it is necessary to circulate a bit pattern. This might be a requirement in the operation
of production machinery or in driving a light display.

The RLF instruction maintains the initial bit pattern by cycling the bits out through the carry flag
and back into the least significant bit position.

Since the carry flag contents get recycled when the RLF instruction is used, we must start our
program by putting the carry flag in a known state ("1 or "0"). Changing the carry flag contents
II

is done using a bit set or bit clear instruction to change bit 0 of the status register (carry flag).

status equ Ox03 ;status word register


c equ 0 ;bit 0 is carry flag
file equ OxOc ;file register wi bit
; pattern
;
bcf status,c ;clear carry flag
rlf file,f ;rotate bits left,
,. result in file

77
To show how this works, let's write a simple program which cycles a bit pattern through the
eight LEDs at port B (output). We will need a time delay to slow things down enough so we can
see what's happening, so we will use the "pause" time delay subroutine (operation explained in
the Timing and Counting chapter). We will start off as shown and rotate left (the RRF
instruction could be used to rotate right).

Carry
Flag

;=======PICT13.ASM=============================6/27/96==
;sequencing demo
; uses time delay "pause"
;-------------------------------------------------------
list p=16f84
radix hex
i----------------------------------------------------- - -
,· cpu equates (memory map)
status equ Ox03
portb equ Ox06
shift equ OxOc
ncount equ OxOd
mcount equ OxOe
i----------------------------------------------------- - -
,· bit equates
c equ 0
i----------------------------------------------------- - -
org OxOOO

start movlw OxOO ;teach port B outputs
tris portb
clrf portb ;all lines low
bcf status,c · ;clear carry flag
movlw b'OlOOlOOl' ;initial bit pattern
movwf shift ;store in shift
get_bit movf shift,w ;get bit pattern
movwf portb ;display
call pause ;delay via subroutine
rlf shift,f ;rotate bits
goto get_bit ;again

78
pause movlw Oxff iM
movwf mcount ito M counter
loadn movlw Oxff iN
movwf ncount ito N counter
decn decfsz ncount,f idecrement N
goto decn iagain
decfsz mcount,f idecrement M
goto loadn iagain
return idone
i
end
i----------------------------------------------------- - -
r at; blast time, select:
·
, memory unprotected
·
, watchdog timer disabled (default is enabled)
·
, standard crystal (using 4 MHz osc for test)
·
, power-up timer on
i=======================================================

If 8 bits plus the carry flag is not enough, how about 16? A double-wide RLF sequence might
look like this:

Second Carry First


Flag

You will need two memory locations for this one and the carry flag must be cleared or set when
the program starts.

The first RLF operating on the memory location shown on the right side of the drawing stuffs
the most significant bit into the carry flag and the carry flag contents into the least significant bit
of the right side memory location.

The second RLF instruction operating on the memory location shown on the left pulls the carry
flag bit into the least significant bit and pushes the most significant bit into the carry flag.

This sequence can be repeated indefinitely, Assuming a larger microcontroller, the contents of
the two memory locations would be sent to two parallel ports after each pair of RLF instructions
have been executed to update the status of the sixteen output lines.

79
SUBROUTINES

The next example will illustrate the use of time delays and subroutines. The program counts in
binary and displays the count at eight LEDs via port B. If the counting were done at full speed,
the LEDs would appear to be all on all of the time. Instead, the time delay subroutine "pause"
will be used to provide a time delay between counts so that each count will be displayed for
about one second. It delays for 0.2 second (200 milliseconds). A call subroutine instruction
(CALL) is used to call the "pause" subroutine. The routine is used five times in succession to
obtain a 1 second delay. The last instruction in the time delay subroutine is return from
subroutine(FUE11J~.

The details of the "pause" time delay subroutine will be explained in the next section (time delay
loop).

A file register called "count" will be used as a counter.

Time Delay Via


Subroutine

80
i=======PICT12.ASM=============================6/27/96==
isubroutine demo
i uses time delay "pause"
i----------------------------------------------------- - -
list p=16f84
radix hex
i----------------------------------- ------------------ - -
·
,
portb
cpu equates (memory map)
equ Ox06
count equ OxOc
ncount equ OxOd
mcount equ OxOe
i----------------------------------------------------- - -
org OxOOO
i
start movlw OxOO iteach port B outputs
tris portb
clrf portb iall lines low
clrf count iinitialize counter
get_cnt movf count,w iget count
movwf portb idisplay count
call pause idelay via subroutine
call pause
call pause
call pause
call pause
incf count,f iincrement counter
goto get_cnt iagain

pause movlw Oxff iM
movwf mcount ito M counter
loadn movlw Oxff iN
movwf ncount ito N counter
decn decfsz ncount,f idecrement N
goto decn iagain
decfsz mcount,f idecrement M
goto loadn iagain
return idone

end
;-------------------------------------------------------
iat blast time, select:
i memory unprotected
i watchdog timer disabled (default is enabled)
i standard crystal (using 4 MHz osc for test)
·
, power-up timer on
;=======================================================

Note that this program loops until the reset switch is pressed.

81
The "count" register is an 8-bit counter which has 28 = 256 possible combinations of O's and l's.

Subroutines are very useful. You may think of them as program modules which do some
specific task. Once you have written or otherwise obtained a useful subroutine, it is yours to
incorporate into future programs. This saves a lot of work. Also writing and debugging one
subroutine at a time is much easier than trying to write and debug a large program all at one go.

Your main program can call one subroutine after another to do a large job. Also one subroutine
can call another. As long as each subroutine ends with an RETURN or RETLW instruction, the
sequence of operations will work its way back to the main program.

The microcontroller uses a hardware stack as a place to keep track of program addresses as it
moves into and back out of subroutines. The operation of the stack for subroutine return
addresses is automatic.

Remember that a subroutine must end with a RETURN or RETLW instruction.

The PIC16F84 stack is eight deep, meaning that the main program can call one subroutine which
calls a second subroutine, etc. The limit is eight deep.

TIME DELAY LOOP

Sometimes it is necessary to wait a specified period of time for something to happen. This
might be waiting for switch contacts to stop bouncing or holding an EPROM control line high
for a specified time as part of the programming procedure. Time intervals can be measured
using hardware (covered later) or by software using a time delay loop. A time delay loop counts
clock cycles until a time interval has elapsed. The accuracy of the interval depends on the
accuracy of the PIC 16F84 system clock. For accurate delays, a crystal-controlled clock
oscillator is recommended. If a 4 megahertz crystal oscillator is used, the oscillator input to the
PIC16F84 is divided by 4 inside the PIC16F84. So the internal clock frequency is 1 megahertz.

Each instruction executed by the PIC16F84 takes a set number of clock cycles. We will use a
file register as a counter. The number of internal clock cycles required for the instructions we
will be using is shown in the table:

Instruction Clock Cycles

MOVLW 1
MOVFW 1
DECFSZ 1, 2 if result is 0
GOTO 2
CALL 2
RETURN 2

82
PIC16 instructions execute in one instruction cycle except:

• OOTO

• CALL
• Instructions which write to the program counter.

These exceptions require two instruction cycles to execute.

A simple time delay loop using a file register follows:

Load File Register With


NumberN

Continue

Internal
Clock
Cycles
1 MOVLW Load counter
1 MOVWF
lxN DECFSZ * Decrement counter
2xN GOTO Done ?
* 2 instruction cycles required last
time through (count = 0)

83
The number of clock cycles required to run this delay program depends on the number loaded
into the counter at the beginning of the program (N).

MOVLW

17
Total internal clock cycles. 1 + 1 + N +2N + 1
-3N+3
=3N approximately
Last DECFSZ

This is assuming that N is large enough that the additional 3 cycles going into and out of the
delay routine do not cause significant error.

If the PICl6F84 internal clock frequency is 1 megahertz, each clock cycle is 1 microsecond.
If the hexadecimal equivalent of decimal 50 were loaded into the counter, the program would
produce a delay of

3(50) +3 = 153 internal clock cycles


= 153 microseconds

If the program above were used as a subroutine, 2 additional cycles would be required for the
CALL instruction and 2 more for the RETURN instruction for a total of 4 additional cycles.

The maximum delay possible with this program is achieved by loading OxOO, strangely enough.
The decrement instruction will go through to OxFF and so on. The maximum delay is

3(256) +3 = 771 cycles


= 771 microseconds (assuming 4 MHz crystal-
controlled clock oscillator)

It is best not to agonize over the math. Calculate an approximate number and run the program.
Measure the result and change the number if necessary, then try again.

84
Using a program with a time delay subroutine to tum output port B on and off will serve as a
demonstration. Connect an oscilloscope to port B to measure the width of the pulses.

;=======PICT8.ASM==============================6/25/96==
;time delay demo
; file register counter - count to 10
; delay = 10+ microseconds
i----------------------------------------------------- - -
list p=16f84
radix hex
i----------------------------------------------------- - -
·
,
portb
cpu equates (memory map)
equ Ox06
count equ OxOc
i----------------------------------------------------- - -
org OXOOO

start movlw OxOO ;load w with OxOO
tris portb ;copy w tristate, port B
·
,
clrf portb
outputs
;all lines low
go bsf portb,O ;turn on LED
call delay ;delay via sub
bcf portb,O ;turn off LED
call delay ;delay via sub
goto go ; repeat

delay movlw OxOa ; decimal 10
movwf count ;load counter
repeat decfsz count,f ; decrement counter
goto repeat ;not 0
return ;counter 0, end delay

end
;-------------------------------------------------------
; at blast time, select:
·
,
;
memory unprotected
watchdog timer disabled (default is enabled)
; standard crystal (using 4 MHz osc for test)
·
, power-up timer on
i=======================================================

85
call 2
movlw 1
movwf 1
decfsz lxN
goto 2xN
decfsz 1 (last)
return 2.-
7+3N clock cycles or approx. 3N clock cycles

Run the program. Try various hex numbers and measure the time delays. Ox IE gives a delay of
approximately 100 microseconds. Notice that the LO interval is 2 microseconds longer than the
ID. This is because the GOTO (repeat) instruction requires 2 microseconds. This could be
balanced by adding two NOP instructions after turning on the LED.

86
A delay of 200 milliseconds (called "pause") is used for examples in this book. It is generated
using nested loops (loop within a loop). Two counters are required.

87
Internal
Clock
Cycles
2 CALL
1 MOVLW M Load M
1 MOVWF In M counter
lxM MOVLW N Load N
lxM MOVWF IN N counter
lxNxM DECFSZ Decrement N counter
2xNxM GOTO N = a ?
lxM DECFSZ Decrement M counter
2xM GOTO M= a ?
2 RETURN

Total cycles = approximately 3MN.

The maximum possible delay obtainable with this program is 3(256)(256) = 196,608
microseconds = 197 milliseconds (approximately) with a 1 megahertz internal clock.

88
Here is the loop-within-a-loop time delay subroutine "pause" used earlier.

ncount equ OxOd


mcount equ OxOe
,.
pause movlw Ox iM
movwf mcount ito M counter
loadn movlw Ox iN
movwf ncount ito N counter
decn decfsz ncount,f idecrement N
goto decn iagain
decfsz mcount,f idecrement M
goto loadn iagain
return idone

This program uses two file registers as counters. As an exercise, let's assume it is necessary to
generate a 12 millisecond delay.

Time (millisec) Hex Number N = M


12 Ox

Sample calculation:

Desired delay 12 millisec


M = N = Y
3y2 = 12000 microsec = 12 millisec

12000
3
= 4000 y = J4000 = 63.2 decimal = Ox3F

89
Testing a program to count in binary with the count displayed at the LED output port will give
you another opportunity to try a time delay subroutine.

Initialize Counter

..
,..
~

Get Count

~
Display Count

~
Time Delay Via Your
Subroutine

i
Increment Counter

count equ OxOc


,.
movlw OxOO ;teach port B outputs
tris portb
clrf portb ;all lines low
clrf count ;initialize counter
get_cnt movf count,w ;get count
movwf portb ;display count
call your sub ;your delay subroutine
incf count,f ;increment counter
goto get_cnt ; again

The delay should be long enough so you can see each count displayed on the LEDs but not so
long that you get bored waiting for the count to change.

90
LOOKUP TABLES

A lookup table may be used to convert one code to another. Let's say we want
hexadecimal characters to 7-segment signals to drive a display. We will aSSUIDt- _
character is in the least significant nibble of the byte.

----------------------------------
7-SEGMENT
HEX CODE DPgfe dcba
----------------------------------
OxOO Ox3F 0011 1111
01 06 0000 0110
02 SB 0101 1011
03 4F 0100 1111
04 66 0110 0110
05 6D 0110 1101
06 7D 0111 1101
07 07 0000 0111
08 7F 0111 1111
09 6F 0110 1111

l. DP
7 ~
I.e 9
6 ~ a
f

I
l.
5
"... e
f Ib
Output 4 'I 9
~ d
Port B 3 "(

2 "(
~
c el Ie
... b •
DP
Cathod es
1 'f d

0 ~
....

680n.
a

Common Cathode
1
7-segment
LED Display

The proper 7-segment code may be pulled from the table using relative addressing. If the hex
character is added to the base address of the table (program counter contents), the 7-segment
code is stored at that address.

91
We will assume that the hex character to be converted is in the program line which begins with
the label "char" and that the 7-segment equivalent is to be displayed (Ox02 shown as example).

i=======PICT14.ASM============================10/13/97==
ilookup table demo - 7-segment LED display
i----------------------------------------------------- - -
list p=16f84
radix hex
;-------------------------------------------------------
,. cpu equates (memory map)
pc equ 02 iprogram counter
portb equ 06
i---------------------- ------------------------------- - -
org 0
i
start movlw OxOO iload w with $00
tris portb iteach port B all outputs
clrf portb iall lines low
char movlw Ox02 itest number
call segmnt icall subroutine
movwf portb idisplay results
circle goto circle r done
i
segmnt addwf pc,f iadd offset to program counter
retlw Ox3f iO seven segment
retlw Ox06 i1
retlw Ox5b i2
retlw Ox4f i3
retlw Ox66 i4
retlw Ox6d i-5
retlw Ox7d i6
retlw Ox07 i7
retlw Ox7f i8
retlw Ox6f i 9
i
end
i----------------------------------------------------- - -
r at blast time, select:
i memory unprotected
watchdog timer disabled (default is enabled)
,.
i
standard crystal (using 4 MHz osc for test)
,. power-up timer on
i===================================================== ==

The processor adds the hex character to the program counter where it will be used as the index
or offset to find the 7-segment code which is then displayed.

Store a hex character with a OxO in front of it (i.e. Ox04, etc.) in the program line which begins
with the label "char" . Run the program. Examine the 7-segment display to see if the program
worked.

92
The ADDWF instruction adds 8 bits to the lower 8 bits of the program counter and does not
effect the high 5 bits. The high 5 bits can be dealt with once program memory paging is
understood. For now, tables must be located entirely within the first 256 words of program
memory.

SUBROUTINE LIBRARY

I would encourage you to start a subroutine library. This can include subroutines you write to do
various tasks and subroutines you find in magazine articles, on the Internet news groups or
wherever. The subs can be saved and stored as text files for future use. This saves reinventing
them each time they are needed.

CUT AND PASTE

Windows-based text editors, such as the one included in MPLAB, provide for cutting and
pasting blocks of text. This is a very convenient method for creating new programs using
portions of existing ones. I like to hide code chunks below/after the end directive in a program
listing where the assembler won't assemble them. I can move them into or out of a program at
will during the process of writing and debugging code.

TRY YOUR OWN EXPERIMENTS

I also encourage you to try some ideas on your own. You can combine some of the techniques
from the examples such as count 0 to 9 with time delay and display the count on a 7-segment
display. Use your imagination!

THERE'S MORE --- LOTS MORE!!!!

The programming information given here is intended as an introduction and as a basis for
designing and building your own microcontroller-controlled systems. The information is
complete enough for many applications. If you can't find information you need here, I
encourage you to consult Microchip's data books and their Embedded Control Handbook. One
of the fun things about working with microcontrollers is that there is always more to learn and
more exotic things that you can do.

93
INTERRUPTS

When an event occurs which demands the microcontroller's attention, an interrupt may be
generated which will cause the microcontroller to drop what it is doing, take care of the task that
needs to be performed, and go back to what it was doing.

When an interrupt occurs, the instruction currently being executed is completed. Then the
PIC16F84 jumps to address OxOO4 in program memory and executes the instruction stored there.
This program is called an interrupt service routine. An interrupt service routine may cause (as
required) the microcontroller to first take notes on the status of the program it was executing
when the interrupt occurred so that it can find its place when it comes back. Then the interrupt
service routine will handle the interrupt by doing whatever needs to be done. On completion,
the routine will review its notes, set everything back to the way it was and take up the main
program where it left off.

Interrupts are caused by events which must trigger a response from the microcontroller at the
time they occur. For the PICl6F84, interrupts may come from one of four sources:

• External - outside the microcontroller via the RBO/INT pin.

• Timer/counter TMRO overflow from OxFF to OxOO.

• Port B logic level change on bits 7,6,5,4.

• EEPROM write complete (not covered in this book because bank switching
is required).

Interrupts may be enabled or disabled (masked) at two levels, global (all interrupts regardless of
source) or specific (enable/disable specific interrupt sources).

94
INTERRUPT CONTROL REGISTER

The interrupt control register (INTCON) at address OxOB handles enable/disable and contains
the global interrupt flag and the flags for each interrupt source.

7 6 5 4 3 2 0

GIE I EEIE I TOlE I INTE I RB IE I TOIF I INTF I RBIF I POR = ooooooox

L RB Port Change Interrupt Flag


o = None Of RB 7,6,5,4 Inputs
Changed
1 = At Least One Of These
Inputs Changed
(Must Be Cleared By
Software)

External Interrupt Flag


o = No Interrupt Occured
1 = ExternallNT Occured
(Must Be Cleared By Software)

TMRO Overflow Interrupt Flag


o = No Overflow
1 = TMROOverflowed
(Must Be Cleared By Software)

RB Port Change Interrupt Enable


0= Disables
1 = Enables

L-- INT Interrupt Enab le


0= Disables
1 = Enables

'------- TOlE TMRO Interrupt Enable


0= Disables
1 = Enables

EE Write Complete Interrupt Enable (Ignore)


Global Interrupt Enable
o = Disables All Interrupts
1 = Enables All Enabled Interrupts

95
INTERRUPT SOURCES

External Interrupts

Using external interrupts requires both hardware and software. Hardware must be provided to
sense an event or condition which requires an interrupt to bring about some action . A signal
must be generated and fed to the microcontroller INT pin.

RBO/INT is a general purpose interrupt pin. It is edge-triggered. The INTEDG bit in the option
register determines whether a rising or falling edge triggers an interrupt.

6
Option Register I INTEDGI=
L Interrupt Edge Select
o• Interrupt On Falling Edge
1 • Interrupt On Rising Edge

An INT interrupt can be disabled using the !NT enable (INTE) flag in the INTCON register (bit
4) so that interrupts will be ignored until the INTE flag is set. INT interrupts can be serviced or
ignored under software control.

If an INT interrupt occurs, the INTF flag (bit 1) in the INTCON register is set. The INTF flag
must be cleared via software as part of the interrupt service routine before reenabling the
interrupt or continuous interrupts will occur.

• Disable further interrupts (clear INTE flag).


• Service the interrupt.
• Clear INTF interrupt flag.
• Enable interrupts (set INTE flag).

Timer/Counter Interrupt

Timer/Counter TMRO interrupts occur on overflow from OxFF to OxOO. This is described in the
Timing and Counting chapter.

96
Port B Interrupt On Change· Bits 7,6,5,4

An interrupt on logic level change on port B bits 7,6,5,4 sets INTCON bit 0 (RBIF). This
interrupt is enabled/disabled via INTCON bit 3 (RBIE). Only port lines 7,6,5,4 configured as
inputs are effected.

The pin's value in input mode is compared with the old value latched in the last reading of port
B. The "mismatches" of the pins are OR'ed together to generate the RBIF interrupt (INTCON
bit 0).

The interrupt may be cleared by:

• Disabling the interrupt by clearing the RBIE bit (INTCON bit 3).

• Read port B, then clear the RBIF bit. This ends the "mismatch" condition and allows
RBIF to be cleared.
The interrupt on change feature is recommended for wakeup on key depression operation and
operations where port B is only used for the interrupt on change feature. Polling of port B is not
recommended while using the interrupt on change feature . Reading the port messes up the
mismatch.

GLOBAL INTERRUPT ENABLE FLAG (GIE)

The occurance of an interrupt clears the global interrupt enable flag disabling further interrupts
while the interrupt is being serviced. As the interrupt service routine is completed, execution of
the return from interrupt (RETFIE) instruction sets the global interrupt flag enabling further
interrupts.

SAVING STATUS DURING AN INTERRUPT (CONTEXT SAVING)

When an interrupt occurs, the program counter contents are saved on the stack automatically.
The microcontroller needs to know where to resume code execution when servicing the interrupt
is completed. Saving the status of other registers is the responsibility of the programmer and
must be done to the extent the application requires as part of the interrupt service routine.

• Store W (must be saved first).


• Store status register.
• Execute interrupt service.
• Restore status register.
• Restore W.
• Return from interrupt (RETFIE).

97
save movwf temp_w isave w contents
swapf status,w iswap status, result in w
movwf temp_s isave status contents (swapped)
,.
i1nterrupt service ends with
,.
swapf temp_s,w ireswap status, result in w
movwf status irestore status
swapf temp_w,f iswap, back in file
swapf temp_w,w ireswap, result in w
retfie ireturn with proper W contents

The SWAPF instruction will move data without effecting the status register (Z-flag). Of course
the upper and lower nibbles get swapped in the process. The SWAPF instruction is needed to
replace the status register contents without effecting it (can't use MOVF), so a swap must be
made during the save to offset the swap which will occur on restore.

It took me quite a while to figure out why in the *@! SWAPF instructions were used in the
examples of context-saving code I found. The MOVF instruction can't be used here because the
Z-flag gets corrupted.

An interrupt service routine must end with a return from interrupt instruction (RETFIE).
Execution of the RETFIE instruction causes the program counter to be loaded with the address
saved on the stack when the interrupt occurred and execution resumes where it left off.

WHERE TO PUT THE INTERRUPT SERVICE ROUTINE

The interrupt vector built into the PICl6F84 is Ox004. When an interrupt occurs, the interrupt
vector points to program memory address OxOO4 where the first instruction of the interrupt
service routine must be stored.

98
When interrupts are not used, the main program may start at address OxOOO and run right
through OxOO4 without conflict. If interrupts are used, other arrangements must be made by the
programmer.

Interrupt Vector
Points Here

OxOOO Ox001 Ox002 Ox003

\- First Instruction Of
Main Program - "Start"
First Instruction Of
Interrupt Service Routine

Probably the easiest thing to do is:

org OxOOO
goto start ;real start of main program

org OxOO4
goto iservice ;real start of interrupt service

;start your code
·
,

;iservice your routine

Let the assembler locate the main program and interrupt service routine in program memory.

INTERRUPT LATENCY

When an interrupt occurs, there will be a delay (latency) before the interrupt service routine is
executed. This delay will be 3 or 4 instruction cycles.

99
MULTIPLE EXTERNAL INTERRUPT SOURCES

If more than one interrupt is possible, the hardware will generate signals to interrupt the
microcontroller and also tell it which function caused the interrupt. A different software
subroutine may be necessary for each interrupt source.

A microcontroller such as the PICl6F84 may have only one interrupt line available for general
system use. If more than one interrupt source is required, the microcontroller can poll an input
port line associated with each interrupt source. Software checks each possible source to see
which one needs service. Priorities can be assigned by selecting the order in which sources are
polled, starting with the most important source first,

For systems with multiple interrupt sources, a flip-flop may be used to remember that an
interrupt has been generated by a particular source. The microcontroller will need a sustained
indicator (sometimes called a flag) to find the source of the interrupt (by reading an input port
line). When the microcontroller finds the source, it can clear the flip-flop (via an output port
line), to make it ready for the next interrupt.

...
~ INT Output
Interrupt
Source
PIC16F84
I--

~
Input ~

+5VDC

A
SET
~ CLK a
Flip-Flop
74HC74

+5VDC 0
CLR
a / N.C.

H.

One flip - flop is required for each


interrupt source. Used as a flag.

100
EXAMPLE· EXTERNAL INTERRUPT
INT is edge sensitive. It will respond to a rising edge if the INTEDG bit (bit 6 in the option
register) is set, or to a falling edge if the INTEDG bit is clear.

To generate an INT interrupt, the !NT pin must detect the edge of a pulse. For demonstration
purposes, this can be done using a momentary contact toggle switch with a debouncing circuit
followed by a half-monostable (one-shot) circuit which generates a negative-going pulse of 10
or more microseconds duration.

PULSER CIRCUIT

0 .05~
."..
"X>----I. TOCKI

330n

T -300C-16 ussc
Momentary
Contact
Switch 74HC14

The pulser output is normally logic 1 and the output is a negative-going pulse. We will set up to
respond to the falling edge.

When an !NT interrupt occurs, the microcontroller:

1) Completes execution of the current instruction.


2) Tests the global interrupt enable flag. If the flag is set, interrupts are enabled.
3) Tests the INT interrupt enable flag. If the flag is set, INT interrupts are enabled and the
microcontroller will begin the interrupt sequence.
4) If either interrupt enable flag indicates "disabled", the microcontroller will continue
whatever it was doing when the interrupt signal was received and ignore the interrupt.
5) Clears the global interrupt enable flag to prevent further interrupts (automatic on
recognition of interrupt).
6) Saves the address of the next instruction on the stack (automatic).
6) Jumps to the address pointed to by the INT vector = Ox004.

101
The following test program used in conjunction with the pulse circuit described above will serve
to demonstrate an !NT interrupt.

+5VDC

10K
-U-
RBO/INT RAo

PIC16F84 i
RB1

RB2

Interrupt Switch
Indicator Status
Indicator

102
Main Set UpTo Detect Falling
Program Edge On INTLine

LEOs Off

LEDOn

LED Off

Interrupt
Service
Routine

103
The program scans the status of the switch connected to port A, bit 0 and displays its status at
port B, bit 1. Its operation serves as something to do for demonstration purposes while waiting
for the interrupt to occur. The output is visible, so operation of the program can be verified by
changing switch settings while the program runs. Note that the !NT interrupt is enabled
(essential).

If an !NT interrupt occurs, the microcontroller jumps to OxOO4 where the interrupt service
routine begins. The interrupt service routine toggles the interrupt indicator LED at port B, bit 2
indicating an interrupt has occurred and then returns to the main program.

The port B pullups are turned off. Port B, bit 0 must be an input to receive the interrupt. The
program calls for response to a falling edge on the INT line.

Program a PIC16F84 with both programs. Power-up your test circuit. Change the position of
the switch on port A, bit 0 to confirm that the main program is running. Pulse the INT line
several times and observe the result at the LED connected to port B, bit 2.

The last instruction in an interrupt service routine must be a RETFIE (return from interrupt).
This sends the processor back to the main program.

The register contents are not saved by the interrupt service routine in this example because the
data is not needed.

Remember that an interrupt should not occur during a timing loop as it wi11lengthen the loop by
the time required to service that interrupt. Also, an interrupt which occurs while the PICl6F84's
timer is in use mayor may not be serviced before the timer times out.

The use of interrupts greatly enhances the power of the microcontroller. Interrupts may be
periodic, as determined by a real time clock, or may be related to an event such as a counter
counting down to 0 or a burglar tripping an alarm. The microcontroller does not have to go
around and around in a loop waiting for these things to happen, so it can perform other useful
tasks in the meantime.

104
;=======PICT15.ASM=============================10/12/97==
;INT interrupt demo
i----------- ---------------------------- -------------- - - -
list p=16f84
radix hex
;--------------------------------------------------------
; cpu equates (memory map)
porta equ 05
portb equ 06
intcon equ Ob
;--------------------------------------------------------
org o
goto start ;skip over location pointed
ito by interrupt vector
org 4
goto iserv

start movlw b'10111111' ;falling edge
option
movlw Oxff
tris porta ;teach port A all inputs
movlw b'OOOOOOOl' ;teach port B
tris portb ;bit 0 INT, rest outputs
clrf portb ;port B, bits 7-1 low
bcf intcon,l ;clear INT flag
bsf intcon,7 ;enable global interrupts
bsf intcon,4 ;enable INT interrupts
test btfss porta, 0 ;test port A, bit 0
goto clrb 1
setb 1 bsf portb,l ;set port B, bit 1
goto test

clrb 1 bcf portb,l ;clear port B,bit 1
goto test

iserv bcf intcon,l ;clear INT flag
movlw b'OOOOOlOO' iset up for complement bit 2
xorwf portb,f i xor with "1" changes bit to
; complement
ret fie ireturn from interrupt

end
;--------------------------------------------------------
;at blast time, select:
; memory unprotected
·
,
i
watchdog timer disabled (default is enabled)
standard crystal (using 4 MHz osc for test)
·
, power-up timer on
;================================================= =======

105
TIMING AND COUNTING

DIGITAL OUTPUT WAVEFORMS

Digital output waveforms are easy to generate by writing ones and zeros to a port line. A
positive going pulse of short or long duration may be output by initializing the line to 0,
outputting a l , using a software timing loop or hardware timer to measure the pulse duration,
and then writing a 0 to the port line.

Square waves are easy to generate as you know from some of the examples:

DelaysAre Equal

A rectangular wave is produced if the delays are not equal.

If the delays are changed each time around the loop, sweep frequencies or frequency-modulated
signals may be generated.

As an alternative, the PICl6F84 timer/counter may be used. An advantage is that the


microcontroller is not tied up generating repetitive waveforms.

107
TIMING AND COUNTING
USING THE PIC16F84'S ON-BOARD TIMER/COUNTER

The PICl6F84 timer/counter is referred to as the TIMBRO (TMRO) module. I will simply refer
to it as the timer/counter.

The timer/counter's features are:

• 8-bit.
• Read/write.
• 8-bit software programmable prescaler.
• Internal or external clock.
• Edge-rising or falling (external clock).
• Increments.
• Interrupt on overflow from OxFF to OxOO with flag output.

The PIC16F84 timer/counter has an interrupt on overflow from OxFF to OxOO and is capable of
doing other tasks while timing/counting is going on.

The option register is associated with both the timer/counter and the watchdog timer.

7 6 5 43210

I RBPD I INTEDG I TOCS I TOSE IPSA IPS2 IPS1 IPSO I POR-OxFF

~ Prescaler Value
Prescaler Value
PS2 PS1 pSO ~
0 0 0 2
Prescaler Ass ignment 0 0 1 4
0 .. TMRO 0 1 0 8
1 = WDT 0 1 1 16
1 0 0 32
' - TMRO External Clock Edge Select 1 0 1 64
o.. Increment On Rising Edge 1 1 0 128
1 .. Increment On Falling Edge 1 1 1 256

' - TMRO Clock Source Select


o = Internal Instruction Cycle Clock
1 = External Via TOCKI Pin

Interrupt Edge Select


0= Interrupt On Falling Edge
1 = Interrupt On Rising Edge

Port B Pullup Enable


0= Enabled
1 .. Disabled

108
The option register is written to by executing the OPTION instruction causing the contents of
the W register to be transferred into the option register. There is another method which requires
file register bank switching which we will disregard for now.

Input

T'------
Divide Input Count Output

~rl
Internal
Clock Counter Flag
~
Presealer

Timer/Counter
Input Pin (Pin3)
~
The clock source may be either the PICI6F84's internal instruction cycle clock or the TOCKI
pin. An external clock may be an oscillator running (much) slower than the PIC 16F84's clock
oscillator or it might be a source of pulses to be counted .

The input is either fed directly to the timer/counter (bypassing the prescaler) or through an 8-bit
software programmable prescaler.

The prescaler is assigned to either the timer/counter or the watchdog timer under software
control by using the OPTION instruction. Details later.

The prescaler value may be l-of-8 as determined by the value in the option register bits 2,1,0
(see table). Timing/counting may be done without the prescaler by assigning the prescaler to the
watchdog timer (the only way to do it).

When the prescaler is assigned to the timer/counter, all instructions which write to the
timer/counter register f1 (OxOl) will clear the prescaler.

CLRF
MOVWF
BSF
Etc.

If an external clock source is used with no prescaler, synchronization of the external clock input
must take place. This requires a short sampling procedure plus a delay after synchronization
occurs and prior to the timer/counter being incremented.

There are some requirements for an external clock signal.

No Prescaler

Input high for at least 2 Tosc.


Input low for at least 2 Tosc.

With Prescaler

Input period of at least 4 Tosc divided by the prescaler value.


Highs and lows must be of greater than 10 nanoseconds duration.

109
Tosc is the period of the PIC16F84 clock oscillator.

If there is a write to the timer/counter, incrementing is inhibited for the next 2 instruction cycles.
This can be compensated for by adjusting the number loaded in the timer/counter.

External clock pulses may be detected on their rising or falling edge (software selectable via bit
6 in the option register).

The timer/counter outputs are:

• Reading the timer/counter register (OxOl).


• Interrupt on overflow from OxFF to OxOO.

The timer is incremented by incoming pulses. When the count climbs through OxFF, the count
starts over at OxOO. The timer may be incremented over and over if need be and the number of
times the counter reaches a certain value may be counted using a file register as a counter.

PRESCALER
There is an 8-bit counter which may be used either as a prescaler for the timer/counter or as a
post-scaler for the watchdog timer. This counter is simply referred to as the prescaler instead of
worrying about "pre" vs. "post".

The prescaler divides the clock input by one-of-eight values which effectively reduces the
frequency of the clock. The prescaler is used to divide the input by:

1 (bypass scaler by assigning it to the watchdog timer)


2
4
8
16
32
64
128
256

The only way to feed the clock input directly to the timer/counter is to get the prescaler out of
the way by assigning it to the watchdog timer. The watchdog timer is not given much attention
in this book but we at least have to be able to properly assign the prescaler to it.

The prescaler assignment and ratio are determined by 5 bits in the option register. When the
prescaler is assigned to TMRO, all instructions which write to TMRO such as CLRF, MOVWF,
BSF, etc. will clear the prescaler to prepare it for division of the input signal.

110
Changing Prescaler Assignment
From TMRO To WDT

clrf tmrO iclear timer/counter


clrwdt iclear watchdog timer
movlw b'xxxxlxxx' iprescaler assign to WDT
option i new prescale value

From WDT To TMRO

clrwdt iclear WDT and prescaler


movlw b'xxxxOxxx' iselect TMRO, prescale value
option i and clock source

This sequence must be used even if the watchdog timer is disabled.

The CLRWDT instruction should precede switching the prescaler assignment.

111
USING THE TIMER/COUNTER

Setting up the timer/counter

• Assign prescaler per procedure above.


• Set up the timer/counter by sending the proper bits to option register.

Starting the timer/counter

Write a number to the timer/counter file register.

Counter

- OXFF}.-- Interrupt Occurs On Overflow

Count oxFF - N Times


Counter Is
Incremented
.-- Counter Starts Counting Up From Here

} N Load Timer/Counter With ·W


- OxOO

How do we know the timer/counter Is doing something?

• Successive reads of the timer/counter file register or test a bit in the timer/counter
file register.
• Interrupt on overflow OxFF to OxOO. This is how we know the timer/counter is
finished counting. The PIC16F84 is free to do other things while the timer/counter
is doing it's thing. The interrupt flag is the output.

Timer/counter will keep counting as long as:

• It is not cleared or written to by program instructions.


• The microcontroller is not reset.

Timer/counter must be reloaded after each overflow for repeating time


intervals

If this is not done, the count will start at OxOO each time.

Stopping the timer/counter

Can't - it just runs.

Experiments follow which will illustrate the use of the timer/counter.

112
TIMER/COUNTER EXPERIMENTS

Digital Output Waveform Using TMRO • Internal Clock

Use internal clock divided by 256.


Blink an LED at fast rate - delay 8.2 milliseconds (view with oscilloscope).

ClearWDT
Main
Prepare For Prescaler
Program Assignment
PIC16F84

Set Up TMRO & Assign


PrescalerTo TMRO RBO t--- ---,

Time Delay
ClearTMRO Start Timer/Counter
Su broutlne L...- ,....-_ _----'

Yes

113
Port B Pullups Disabled (Not Used)

External Interrupt On Rising Edge (Not Used)

Clock Source Internal

Option Register

~
PORmOXFF
L Prescaler Value _ Divide By 256
Prescaler Assigned To TMRO

Increment On Falling Edge-


External Clock (Not Used)

The timer/counter may be read as a whole or a single bit may be tested as is done in this
example. When bit 5 of the timer/counter increments to "1", the count is 32. This works for
numbers which are a power of 2.

The delay is roughly 256 microseconds per pulse into lMRO times 32 (via TMRO bit 5) = 8.2
milliseconds.

i=======PICT7.ASM================================6/25/96==
itime delay demo
i tmrO, internal clock divided by 256
i watch tmrO, bit 5 = count to 32
i delay = 8.2 milliseconds
i----------------------------------------------------- - - - -
list p=16f84
radix hex
i----------------------------------------------------- - - - -
i cpu equates (memory map)
tmrO equ OxOl
portb equ Ox06
count equ OxOc
i----------------------------------------------------- - - - -
org OxOOO
i
start clrwdt iprep for assign prescaler
movlw b'llOlOlll' iassign prescaler,
,. internal clock, divide by 256
option
movlw OxOO iload w with OxOO
tris portb iCOPY w tristate, port B
,. outputs
clrf portb iall lines low

114
go bsf portb,O iturn on LED
call delay idelay via sub
bcf portb,O iturn off LED
call delay idelay via sub
goto go irepeat

delay clrf tmrO iclear TMRO, start counting
again btfss tmrO,5 ibit 5 set ?
goto again ino, clear, again
return iyes, end delay

end
;-------------------------------------------------------
iat blast time, select:
i memory unprotected
·
, watchdog timer disabled (default is enabled)
standard crystal (using 4 MHz osc for test)
i
·
, power-up timer on
;=======================================================

Single Time Interval· Internal Clock


Use internal clock divided by 128 and file register counter.
TMRO increments to OxFF and rolls over. Interrupt generated.
Blink an LED once.

PIC16F84

RBO

115
Main
Program

ClearTMRO Interrupt
Flag

Start Count

Interrupt ClearTMRO
Service
Interrupt Flag
Routine

116
Port B Pullups Disabled (Not Used)

External Interrupt On Rising Edge (Not Used)

Clock Sourc e Internal

Option Regist er

POR=OxFF
L Prescaler Value = Divide By 128
Prescaler Assigned To TMRO

Increment On Falling Edge-


Externa l Clock (Not Used)

The on-time is 1 microsecond/internal clock cycle x 128 x 256 x 256 = 8.4 seconds. TMRO is
incremented 256 times to overflow. The file register labeled "count" is decremented 256 times
to reach O.

i=======PICT16.ASM=============================6/28/96==
itimer/counter demo
i single time interval
i internal clock divided by 128
i file register counter
;-------- ----------- ----------------- -- ---------- ---- ---
list p=16f84
radi x hex
,-------------------------------------------- ------------
i cpu equates (memory map)
tmrO equ Ox01
po rtb equ Ox06
intcon equ OxOb
count equ OxOc
,------ ---- - --- - - -- - --- ------------------ --- --- - ---------
org OxOOO
goto start i s k i p over location pointed
i to b y interrupt vector
org Ox00 4
goto iserv
i
start movlw OxOO i P o r t B outputs
tris po rtb
clrf portb i a l l lines low (bit 0 LED off)
bcf intcon , 2 i c l e a r TMRO interrupt flag
bsf intcon ,7 ienab le global interrupts
bsf intcon ,5 i e n a b l e TMRO interrupts
movlw Oxff i d e c i ma l 256
movwf count i l o a d counter
i
clrwdt iclr WDT prep prescale assign
movlw b ' l1010110 ' i s e t up timer/counter

117
option
i
clrf tmrO istart timer/c, clr prescaler
bsf portb,O iturn on LED
circle goto circle iwait for interrupt
i
iserv bcf intcon,2 iclear TMRO interrupt flag
decfsz count,f icount = O?
retfie ino
bcf portb,O iyes, LED off
round goto round idone, circle

end
;----------------------------------------------------------
iat blast time, select:
,· memory unprotected
,· watchdog timer disabled (default is enabled)
,· standard crystal (using 4 MHz osc for test)
·
, power-up timer on
;==========================================================

Single Time Interval· External Clock


Use external 0.1 second clock (555 l-shot or another PICI6).
Bypass prescaler.
Blink an LED once.

Note: It takes about 25.6 seconds for the LED to tum on, so wait patiently! 256 clock pulses are
needed to overflow TMRO.

Clock 1.J1l\I\..~ TOCKI

PIC16F84

RBO 1 - - --,

118
Main
Program

Clear TMRO Interrupt


Flag

Start Count

Interrupt
Service
Routine

ClearTMRO
Interrupt Flag

119
Port B Pullups Disabled (Not Used)

External Interrupt On Rising Edge (Not Used)

Clock Source External (TOCKI Pin)

Option Register

~
POR.OxFF
L Prescaler Value (Not Used)
Prescaler Assigned To WDT (Bypassed)

Increment On Falling Edge-


External Clock

i=======PICT17.ASM==============================6/28/96==
itimer/counter demo
i single time interval
i external clock, bypass prescaler
i blink LED once
;--------------------------------------------------------
list p=16f84
radix hex
;--------------------------------------------------------
,· cpu equates (memory map)
tmrO equ OxOl
portb equ Ox06
intcon equ OxOb
;--------------------------------------------------------
org OxOOO
goto start iskip over location pointed
i to by interrupt vector
org Ox004
goto iserv

start movlw OxOO iport B outputs
tris portb
clrf portb iall lines low (bit 0 LED off)
bcf intcon,2 iclear TMRO interrupt flag
bsf intcon,7 ienable global interrupts
bsf intcon,5 ienable TMRO interrupts
i
clrf tmrO iclear timer/counter
clrwdt iclr WDT prep prescale assign
movlw b'llllllll' iset up timer/counter
option

clrf tmrO istart timer/c, clr prescaler
bsf portb,O iturn on LED

120
circle goto circle ;wait for interrupt 1st time,
,· done 2nd time

iserv bcf portb,O ;LED off
bcf intcon,2 ;clear TMRO interrupt flag
bcf intcon,5 ;disable TMRO interrupt
retfie ; done

end
;-------------------------------------------------------
;at blast time, select:
·
,
;
memory unprotected
watchdog timer disabled (default is enabled)
; standard crystal (using 4 MHz osc for test)
·
, power-up timer on
;=======================================================

Free Running Mode - Internal Clock

Use internal clock divided by 128.


Output to port B, bit o.

PIC16F84

RBO 1--- - - ;

121
Main
Program

Set Up Interrupt
Register

Set UpTMRO &


Prescaler

Start Count

Interrupt
ClearTMRO Interrupt
Service
Flag
Routine

Yes

122
Port B Pullups Disabled (Not Used)

External Interrupt On Rising Edge (Not Used)

Clock Source Internal

Option Register

POR.OxFF
L Prescaler Value. Divide By 128
Prescaler Assigned To TMRO

Increment On Falling Edge-


External Clock (Not Used)

i=======PICT20.ASM=============================6/28/96==
itimer/counter demo
i free running
i internal clock divided by 128
i 10 counts to overflow
;-------------------------------------------------------
list p=16f84
radix hex
;-------------------------------------------------------
; cpu equates (memory map)
tmrO equ Ox01
portb equ Ox06
intcon equ OxOb
;-------------------------------------------------------
org OxOOO
goto start iskip over location pointed
; to by interrupt vector
org Ox004
goto iserv
,.
start movlw OxOO iPort B outputs
tris portb
clrf portb ;all lines low (bit 0 LED off)
bcf intcon,2 ;clear TMRO interrupt flag
bsf intcon,7 ienable global interrupts
bsf intcon,S ienable TMRO interrupts
;
clrwdt ;clr WDT prep prescale assign
movlw b'11010110' ;set up timer/counter
option
;
movlw OxfS ;10 counts (decimal)
movwf tmrO ;start timer/c, clr prescaler
circle goto circle ;wait for interrupt

123

iserv bcf intcon, 2 iclear TMRO interrupt flag,
i enable further interrupts
btfss portb,O iport B, bit 0 status?
goto setbit ibit is clear
clrbit bcf portb,O iclear port B, bit 0
goto ldtmr ito load timer/counter
setbit bsf portb,0 iset port B, bit 0
ldtmr movlw OxfS i10 counts (decimal)
movwf tmrO istart timer/c, clr prescaler
retfie ireturn from interrupt

end
i----------------------------------------------------- - - - - -
r at blast time, select:
i memory unprotected
i watchdog timer disabled (default is enabled)
··
,
,
standard crystal (using 4 MHz osc for test)
power-up timer on
i==========================================================

Run the program and look at port B, bit 0 with a scope.

Examples:

• Load OxFS, prescaler + 128 (10 counts to overflow)


l~sec x 128/count x 10 = 1.28 msec

1.28 msec

This is the time between each HI/LO or LO/HI transition


at the port line. The time to execute the interrupt
service routine adds to this slightly.

124
• Load OxOO, prescaler + 128

OxOO = 256 decimal 128 ~sec x 256 = 33 msec


Counts to overflow

33 msec

• Load OxOO, prescaler bypassed

1 ~sec x 256 = 256+ ~sec (no allowance for program


overhead)

256+ usee

• Load Ox40, prescaler + 2 (192 counts to overflow)

1 ~sec x 192 x 2 = 384+ ~sec (no allowance for program


overhead)

Free Running Mode - External Clock

It's your turn!

125
Counting Events (Pulses)

Use pulser for input.

.".
TOCKI +5VDC

PIC16F84 10K

RB7-0 RAO
Start with switch closed .

SLED's i-
Open when want to read count.

PULSER CIRCUIT

0.05 Jlf

"X>--1. TOCKI

3300

T .. 300C .. 16 usee

Momentary
Contact
Switch 74HC14

126
ClearTMRO, Prep
Assign

DisplayTMRO Contents
At Port B

127
Port B Pullups Disabled (Not Used)

External Interrupt On Rising Edge (Not Used)

Clock Source External (TOCKI Pin)

Option Register
'--y---J
POR-OXFF
L Prescaler Value (Not Used)
Prescaler Assigned To WDT (Bypassed)

Increment On Falling Edge-


External Pulses

;=======PICT2l.ASM===============================lO/23/97==
;event counting demo
i----------------------------------------------------- - - - - -
list p=16f84
radix hex
i----------------------------------------------------- - - - - -
,· cpu equates (memory map)
tmrO equ OxOl
porta equ OxOS
portb equ Ox06
i----------------------------------------------------- - - - - -
org OxOOO

start movlw Oxff ;port A inputs
tris porta
movlw OxOO ;port B outputs
tris portb
clrf portb ;all lines low (bit 0 LED off)

clrf tmrO ;clear tmrO before assign wdt
clrwdt ;clr WDT prep prescale assign
movlw b'llllllll' ;set up timer/counter
option
clrf tmrO ;clear again to zero

switch btfss porta, 0 ;monitor switch
goto switch
movf tmrO,w ;read TMRO
movwf portb ;display TMRO contents
circle goto circle ; done

end

128
;-------------------------------------------------------
iat blast time, select:
i memory unprotected
i watchdog timer disabled (default is enabled)
i standard crystal (using 4 MHz osc for test)
i power-up timer on
;=======================================================

1). Power-up with switch closed.

• Open switch - all LEDs should be off.

2). Power-up with switch closed.

• Pulse X (few) times.


• Open switch. LEDs display pulse count X.

129
PIC16C54

The PIC16C54 is one of the simplest and certainly the most popular member of the baseline
PIC16C5X family. It is an 18-pin device. The main features, or lack of them, which differenti-
ate the PIC16C54 from the PIC16F84 are:

• EPROM program memory.

• 512 program memory locations.

• 32 file registers. 25 are general-purpose.

• Fewer instructions (4).

• 2-level stack.

• No interrupt capability.

• No program counter high latch.

• No file register bank-switching.

• Reset vector points to OxlFF.


• Port data-direction (TRIS) register is "buried".

• Option register is "buried".

• One timer/counter (RTCC/TMRO).

• The timer/counter RTCC/TMRO will not interrupt the processor on overflow from
OxFF to OxOO.

• No power-up timer.

The PIC16C54 has plenty of features and is ideal for many low-end applications.

131
PINS AND FUNCTIONS

RA2 1 - 18 RA1
RA3 2 - 17 RAO
*RTCCITOCKI 3 16 OSC1/CLK IN
MCLR 4 15 OSC2ICLK OUT
Vss 5 PIC16C54 14 Vdd
RBO 6 13 RB7
RB1 7 12 RB6
RB2 8 11 RB5
RB3 9 10 RB4

* Microchip changed pin and timer/counter names along the way. This is the real time clock
counter (RTCC) input pin which is connected to what is more recently referred to as
TIMERO (fMRO) module timer/counter. Confusing. You will see both in the literature.
Just think of this as the timer/counter pin!

The PIC16C54 is a CMOS device.

PACKAGES

The PIC16C54 is available in the following packages suitable for the experimenter.

Program Memory Package Reprogrammable


EPROM Plastic No, one-time programmable (OTP)
EPROM Windowed Yes, erase with uv light

OTP parts contain an EPROM, but since the parts do not have windows, they cannot be erased.
OTP parts cost less because they don't have windows.

132
CLOCK OSCILLATOR

Four different clock oscillators may be used as with the PIC16C54.

Windowed EPROM parts may be programmed to operate with any of the four clock oscillator
types. This may be changed when the part is erased and reprogrammed.

For the original one-time-programmable (OTP) parts (no A suffix), each part is designed to be
used with one and only one of the four oscillator types. Each part type has a unique part number
(see Microchip data book). The decision of which clock oscillator to use is made prior to pur-
chase.

The newer PIC16C54A (A suffix) OTP parts are designed so that the clock oscillator type is
chosen at the time the chip is programmed. This is the primary difference between parts with
and without the A suffix.

CONFIGURATION BITS

The configuration bits (called "fuses" in some of the older literature) work the same as the
PICl6F84.

A note about the -JW windowed parts - don't turn on the code protection bit! It can't ever be
turned off. The windowed part will become an expensive OTP part.

PORTS

Port A is 4 bits/lines wide and port B is 8 bits/lines wide or byte-wide. Each port line may be
individually programmed as an input line or output line. This is done using a special instruction
(TRIS) which matches a bit pattern with the port lines. A 0 associated with a port line makes it
an output, a 1 makes it an input. Examples follow.

The PIC16C54 does not have port data direction registers as does the PIC16F84. Use of the
TRIS instruction is the way it is done with the PIC16C54. The PIC16C54 was one of
Microchip's first products and this is where the TRIS instruction comes from.

See the data book for port current limit specs (less than PIC16F84).

All unused port lines should be tied to the power supply (CMOS rule - all inputs must go some-
where). On reset, all port lines are inputs.

133
ARCHITECTURE

Program Memory

The PIC16C54 program memory is 12 bits wide and 512 words long.

Program memory may be ROM, EPROM or OTP EPROM. Regardless of type, program memo-
ry is read-only at run time. PIC16s can only execute code contained in program memory.

Program Memory

OxOOO
001
002

Pointed To by -",,-
Reset Vector "::4.
OxlFF

File Registers

The file registers are 8 bits wide with the exception of the program counter which is 9 bits wide.
The PIC16C54 has 32 file registers (OxOO - OxlF).

File Registers

OxOO Indirect Address Indirect Address Pointer *


01 RTCC - TMRO Timer/Counter **
02 PC Program Counter
03 Status Status Register - Flags
04 rile Select Indirect Pointer
05 !Port A Data Port A
06 Port B Data Port B
07

neral Purpose File Registers


hink Of This Area As RAM Or Data Memory

OxlF

* Not Physically Implemented


** Microchip Changed Name Along The Way

134
The first seven file registers have specific dedicated purposes (to be described later). The
remaining 25 file registers are there for your use and may be thought of as RAM or data memory
for storing data during program execution.

Hex
Address
ill OXOO Indirect data addressing register.
See indirect addressing section in programming chapter.
fl OxOl Real time clock/counter register (RTCC or TMRO)
See timing and counting chapter.
f2 Ox02 Program counter.
See relative addressing section in programming chapter.
f3 Ox03 Status word register.
f4 Ox04 File select register (FSR).
See indirect addressing section in programming chapter.
f5 Ox05 Port A - 4-bit, bits 4 - 7 are not implemented and read as O's.
f6 Ox06 Port B - 8-bit
f7 - Ox07 - General purpose registers (RAM).
flF OxlF

Stack
The 2-level stack is in hardware meaning that it is entirely separate from the file registers
(RAM) and cannot overwrite them. Subroutines can be nested 2-deep.

Reset Vector
On reset which occurs on power-up or when the reset switch is used to pull MCLR low, the
PIC16C54 will begin executing instructions at address OxlFF. Typically, a GOTO instruction is
placed there which redirects program execution to address OxOOO where the first program
instruction is stored.

list p=16c54
radix hex
org OxOOO
start movlw OxOO
tris portb
movlw OxOf
movwf portb
circle goto circle
org Oxlff
goto start
end

Note the second ORG statement and code telling the PIC16C54 to go to "start" which is at
OxOOO.

135
Program Counter
The program counter (pC - at Ox02) is 9 bits wide. Bit 8 (9th bit) of the PC is cleared by:

• A CALL instruction.
• Any instruction which writes to the PC.

A GOTO loads all 9 bits of the program counter and will jump to anywhere in the PIC16C54's
program memory space.

A CALL loads the lower 8 bits of the program counter. The 9th bit is cleared to O. All subrou-
tine calls are limited to the first 256 locations of program memory for the PIC16C54.

Any instruction which writes to the program counter changes the low 8 bits and clears the 9th
bit, so computed jumps are limited to the first 256 locations of program memory for the
PIC16C54.

Option Register

7 65 43210

I TOGS I TOSE IPSA IPS2 IPS1 IPSO I POR .. OxFF

'--Y---" Presca ler Value


Prescaler Value
PS2 PS1 PSO ~
o 0 0 2
Prescaler Assignment o 0 1 4
0- TMRO 010 8
1 .. WDT o 1 1 16
1 0 0 32
~ TMRO External Clock Edge Select 1 0 1 64
o = Increment On Rising Edge 1 1 0 128
1 - Increment On Falling Edge 1 1 1 256

~ TMRO Clock Source Select


o-Internal Instruction Cycle Clock
1 - External Via TOCKI Pin

Unimplemented

136
-.Status Register

7 6 5 4 3 2 o
paR - 00011 XXX

Carryl8orrow Rag
ADDWFAndADDLW
Instructions

Digit Carryl8orrow Flag


ADDWF And ADDLW
Instructions

Zero Flag
o- Clear If NotZero
1 - Set If The ResultOf An Arithmetic Or
LogicOperationIs Zero

PowerDownBit
o By Execution Of Sleep Instruction
1 After Power-Up Or By CLRWDT
Instruction Execution

Time-Out Bit
o = A WDTTimeoutHasOccured
1 .. AfterPower-Up And By CLRWDTAnd
SLEEP Instructions

NO TIMER/COUNTER OVERFLOW INTERRUPT/FLAG OUTPUT

With the PIC16C54, the only way to find out the status of the timer/counter is to read it. The
PIC16C54 can't be doing much of anything else while the timer/counter is being used for timing
because it has to watch for timeout.

FEWER INSTRUCTIONS

There are four instructions which are not available:

RETURN Return from subroutine (use RETLW 0 instead).

RETFIE Return from interrupt (no interrupts).

ADDLW k Add literal to W.

SUBLW k Subtract W from literal.

137
The TRIS and option registers are not addressable.

The TRIS and OPTION instructions will work as they do with the PICl6F84.

PIC16C54 PROGRAMMING EXAMPLE

Following is an example for the PIC16C54. It does the same thing as the first example for the
PICl6F84, so you can compare them.

• Note processor type.

• No power-up timer bit.

• ORO statement, OOTO at OxlFF.

;=======PICT54.ASM================================4/2I/96==
list p=16c54
radix hex
;----------------------------------------------------------
·
,
portb
cpu equates (memory map)
equ Ox06
;----------------------------------------------------------
org OxOOO
start movlw OxOO ;load w with OxOO
tris portb ;copy w tristate, port B
·
,
movlw OxOf
outputs
;load w with OxOF
movwf portb ;load port B with contents

circle goto
of w
circle ;circle

org OxIff ;pointed to by reset vector
goto start

end
i----------------------------------------------------- - - - - -
;at blast time, select:
·
, memory unprotected
·
, watchdog timer disabled (default is enabled)
·
, standard crystal (using 4 MHz osc for test)
;==========================================================

138
TIMING AND COUNTING

The PIC16C54 timer/counter is referred to as the RTCC (real time clock counter) or, more
recently as the TIMBRO (TMRO) module. I will simply refer to it as the timer/counter.

The timer/counter's features are:

• 8-bit.
• Read/write.
• 8-bit software programmable prescaler.
• Internal or external clock.
• Edge-rising or falling (external clock).
• Increments.
There is no timer/counter interrupt or flag. The timer/counter must be sampled by reading f1
(Ox01) to determine its status. This means that the PIC16C54 timer/counter may be used for
event counting and for generating time delays. For time delays, the microcontroller must contin-
ually check the count (at least just ahead of time out) which means it can't be doing much else
while timing is going on. The PIC16F84 has a timer/counter with interrupt on overflow from
OxFF to OxOO and is capable of doing other tasks while timing/counting is going on.

An option register is associated with both the timer/counter and the watchdog timer.

• 6-bits.
• Write only.
• In hardware (i.e., not a file register).

Executing the OPTION instruction causes the contents of the W register to be transferred into
the option register.

The clock source may be either the PIC16C54's internal instruction cycle clock or the
RTCCrroCKI pin. An external clock may be an oscillator running (much) slower than the
PIC16C54's clock oscillator or it might be a source of pulses to be counted.

External clock pulses may be detected on their rising or falling edge (software selectable).

The prescaler is assigned to either the timer/counter or the watchdog timer under software con-
trol by using the OPTION instruction.

The prescaler value may be 1-of-8 as determined by the value in the option register bits 2,1,0
(see table). TIming/counting may be done without the prescaler by assigning the prescaler to the
watchdog timer (the only way to do it).

When the prescaler is assigned to the timer/counter, all instructions which write to the
timer/counter register f1 (OXO1) will clear the prescaler.

CLRF
MOVWF
BSF
Etc.

139
If an external clock source is used with no prescaler, synchronization of the external clock input
must take place. This requires a short sampling procedure plus a delay after synchronization
occurs and prior to the timer/counter being incremented.

There are some requirements for an external clock signal.

No Prescaler

Input high for at least 2 Tosc.


Input low for at least 2 Tosc.

With Prescaler

Input period of at least 4 Tosc divided by the prescaler value.


Highs and lows must be of greater than 10 nanoseconds duration.

Tosc is the period of the PIC16C54 clock oscillator.

If there is a write to the timer/counter, incrementing is inhibited for the next 2 instruction cycles.
This can be compensated for by adjusting the number loaded in the timer/counter.

140
TIMER/COUNTER DESCRIPTION

The timer/counter is an 8-bit software programmable counter. Its input is the PICl6C54's inter-
nal clock or an external source via the timer/counter pin fed through an 8-bit software program-
mable prescaler to the counter. The only output is reading the timer/counter register. (OxOl).

Input
Divide Input Count
Internal
Clock

Timer/Counter
Input Pin (Pin3)

The prescaler is used to divide the input by:

1 (bypass scaler by assigning it to the watchdog timer)


2
4
8
16
32
64
128
256
The timer is incremented by incoming pulses. When the count climbs through OxFF, the count
starts over at OxOO. The timer may be incremented over and over if need be and the number of
times the counter reaches a certain value may be counted.

141
USING THE TIMER/COUNTER

Setting up the timer/counter

• Assign prescaler.
• Set up timer/counter by sending the proper bits to the option register.

Starting the timer/counter

Clear the timer/counter file register.

Counter

Counter counts up and will overflow when the count reaches OxFF. After that, the
counter contents mean nothing because there is no way to know an overflow has
occurred.

How do we know the timer is doing something?

Successive reads of the timer/counter file register or test a bit in the timer/counter
file register.

Timer/counter will keep counting as long as:

• It is not cleared or written to by program instructions.


• The microcontroller is not reset.

Stopping the timer

Can't - it just runs and overflows each time the count reaches OxFF.

Prescaler

Divides the clock input by one-of-eight values which effectively reduces the frequency
of the clock.

TIMER/COUNTER EXPERIMENT

This one is your deal! Create an on/off output using the timer/counter. Use a read loop to watch
the timer/counter until it increments to the value you have chosen.

142
MENDING OUR WAYS

SINK VS. SOURCE

The circuit examples which include LEDs show them connected in series with a current limiting
resistor to ground. A logic "I" turns on the LED. This method was chosen because it is
intuitive for the beginner to have a "I" turn on the LED. Current is sourced by the port line with
this arrangement. A better design is shown below:

+SVDC

PIC16F84

RBO 1--- ---'

The port line sinks current and logic "0" turns on the LED. CMOS devices are better at sinking
current than sourcing it. The maximum sink and source current by any I/O pin is 25 rnA and 20
rnA respectively. The maximum sink or source current for a port at any given time is as follows:

Any r/o Pin Port A Port B

Sink current 25 rnA 80 rnA 150 rnA


Source current 20 rnA 50 rnA 100 rnA

143
FILE REGISTER BANK SWITCHING

The option and TRIS registers are not really buried after all. There are two banks of file
registers, bank 0 (the one you know about) and bank 1.

File Registers

OxOO Indirect Address* Indirect Address* Ox80


01 TMRO Option 81
02 PCL PCL 82
03 Status Status 83
04 File Select File Select 84
05 Port A Data TRISA 85 Direct Addressing A File Register
06 Port B Data TRISB 86
07 87 7 6 o
08 Ignore
Ignore
Ignore
Ignore
88
89
D ,..-----;---,..-----;---r----r-----;
r - - I

!
09
OA PCLATH PCLATH 8A
OB INTCON INTCON 8B
OC 8C 7 Bits From Opcodo
36 From RPO In Status Register
General Purpose Mapped In (comes up "0" on reset)
File Registers Bank 0 **

Ox2F OxAF
BANK 0 BANKl
* Not physically implemented
** Example: A write to Ox8C will result
in data appearing at OxOC

The control bit for bank switching is located in the status register.

RPO bit 5

o = bank 0
1 = bank 1
Notice that some of the special purpose file registers appear in both banks. They will be
accessed regardless of which bank is selected at the time. If RPO is 1 and a general purpose file
register is accessed, bank 0 will be accessed. The most significant bit of the direct address will
be ignored.

File registers Ox08, Ox09, Ox88 and Ox89 have to do with programming the 64 x 8 EEPROM
data memory which has it's own address space (beyond the scope of this book).

144
Soooo ..... if you want to write to the option register directly instead of using the ("illegal")
OPTION instruction:

status equ Ox03


rpO equ 5
,.
bsf status,rpO iswitch to bank 1
movlw value iload W with proper value
movwf opt reg iflip bit(s) in option register
bcf status,rpO iswitch back to bank 0

If you want to write to the port B tristate register directly instead of using the ("illegal") TRIS
instruction:

status equ Ox03


rpO equ 5
trisb equ Ox86
;
bsf status,rpO iswitch to bank 1
movlw b'OOOOllll' iinputs vs. outputs
movwf trisb
bcf status,rpO ; switch back to bank 0

BANK SWITCHING DEMO

The time delay demo program from page 108 is modified here to show how bank switching
works.

;=======PICT24.ASM=============================8/ll/96==
;time delay demo
; tmrO, internal clock divided by 256
; watch tmrO, bit 5 = count to 33
i delay = 8.4 milliseconds
;-------------------------------------------------------
list p=16f84
radix hex
i----------------------------------------------------- - -
,. cpu equates (memory map)
tmrO equ OxOl
status equ Ox03
portb equ Ox06
count equ OxOc
opt reg equ Ox8l
trisb equ Ox86
;-------------------------------------------------------
,. bit equates
rpO equ 5
,._------------------------------------------------------

145
org OxOOO

start clrwdt iprep for assign prescaler
bsf status,rpO iswitch to bank 1
movlw b'llOlOlll' iassign prescaler,
i internal clock, divide by 256
movwf opt reg iwrite to option register
movlw OxOC iload w with OxOO
movwf trisb iwrite to tristate B, port B
,· outputs
bcf status,rpO iswitch to bank 0
clrf portb iall lines low
go bsf portb,O iturn on LED
call delay idelay via sub
bcf portb,O iturn off LED
call delay idelay via sub
goto go i repeat

delay clrf tmrO iclear TMRO, start counting
again btfss tmrO,5 ibit 5 set ?
goto again ino, clear, again
return iyes, end delay
i
end
;------------------------------------------ ----------------
r at; blast time, select:
,· memory unprotected
,· watchdog timer disabled (default is enabled)
i standard crystal (using 4 MHz osc for test)
,· power-up timer on
;==========================================================

In the second line of the program the BSF instruction is used to set the RPO bit (bit 5) in the
status register which selects file register bank 1. While bank 1 is selected, the option register is
written to (select timer options) and the TRISB register is written to (port B data direction).
Then the RPO bit is cleared to switch back to bank O. All this is straight forward with one
exception! The file register memory map for the PIC16F84 shows the follow addresses:

Register Bank Address

option 1 Ox8l
trisb 1 Ox86

Using these addresses in the CPU equates results in two MPASM assembler warnings. These
warnings relate to the two registers and say "Argument out ofrange---Ieast significant bits used." .
These warnings can be ignored, but it useful to know why they appear.

146
When direct addressing a file register, the low-order 7 bits come from the opcode (address label
in the instruction) and the 8th bit (most significant bit = bit 7) comes from the RPO bit in the
status register.

File Register Address


7 6 0

1 1
7 ens From Opcod,

R'9;S;
Bit 7 Comes From Bit 5 (RPO) In
Status

7 5 0
1----,-------,--------,----,------,---,-------,---,
1_ _ Status Register
o os Bank 0

1 os Bank 1

Sooo in the case of TRISB, the address Ox86 used with the instruction (trisb equ Ox86) will
supply the low order 7 bits 0000110 and the RPO bit will supply bit 7=1 giving the address
10000110 = Ox86.

7 0

\010 \01 0 1
1 1
1 1
0 1

_ _ _ ----'II I
Ox8 Ox6
I I
Ox86

The assembler warnings may be avoided by using a technique which is beyond the scope of this
book. Simply ignore them for now.

147
INTERRUPTS AND BANK SWITCHING

From the point of view of saving context when an interrupt occurs, the status register will be
accessed whether in bank 0 or 1 at time of interrupt Restoring the contents of the status register
at the end of the interrupt service routine will take care of selecting the proper file register bank
prior to resumption of main line code execution.

In terms of the interrupt service routine itself, it would be well to switch to bank 0 at the start of
the routine in case the microcontroller was in bank 1 at the time the interrupt occurred. This
should be done if your program includes bank switching.

status equ Ox03


rpO equ 5
i
bcf status,rpO iselect bank 0

File register bank switching is not used in the PIC16C54 (FSR bits 7,6,5 are not implemented).
File register bank switching is used in:

PIC16C57,58
PIC16C7X
PIC16F8X

PROGRAM MEMORY PAGING

Program memory is divided into pages as follows:

12-bit Core 14-bit Core


Base-line Mid-range

Memory Locations 512 2K


Per Page

Program memory page selection may be required (if your program must occupy more than page
0) by setting control bits in a register. This is beyond the scope of this book, but be aware that
this requirement exists. This topic is covered in PIC'n Up The Pace.

The PICl6F84 has 1K of program memory (less than 2K, mid-range part) and program memory
paging is not required. The PIC16C54 has 512 words of program memory and program memory
paging is not required. The PIC16C57, 58 (base-line parts) have more than 512 words of
program memory, so paging is required for programs of more than 512 words.

INCLUDE FILES

The processor-specific equates which are used repetitively may be placed in a file called an
"include" file which may be included in the assembly process. This saves creating the equates
each time you write a new program. Using the time delay demo program again as an example,
the destination designator, CPU and bit equates are removed from the program listing and placed
in a separate include file named 16F84.INC.

148
Program:

i=======PICT25.ASM============================10/13/97==
itime delay demo
i tmrO, internal clock divided by 256
i watch tmrO, bit 5 = count to 33
i delay = 8.4 milliseconds
i----------------------------------------------------- - -
list p=16f84
radix hex
include <16F84.INC>
i----------------------------------------------------- - -
org OxOOO

start clrwdt iprep for assign prescaler
bsf status,rpO iswitch to bank 1
movlw b'11010111' iassign prescaler,
i internal clock, divide by 256
movwf opt reg iwrite to option register
movlw OxOO iload w with OxOO
movwf trisb iwrite to tristate B, port B
i outputs
bcf status,rpO iswitch to bank 0
clrf portb iall lines low
go bsf portb,O iturn on LED
call delay idelay via sub
bcf portb,O iturn off LED
call delay idelay via sub
goto go i repeat
i
delay clrf tmrO iclear TMRO, start counting
again btfss tmrO,5 ibit 5 set ?
goto again ino, clear, again
return iyes, end delay

end
i-----------------------------------------------------
iat blast time, select:
,· memory unprotected
,· watchdog timer disabled (default is enabled)
,· standard crystal (using 4 MHz osc for test)
·i=====================================================
, power-up timer on

149
Include file:

;=======l6F84.INC================================lO/l3/97==
;time delay demo include file
;----------------------------------------------------------
.
, cpu equates (memory map)
tmrO equ OxOl
status equ Ox03
portb equ Ox06
count equ OxOc
opt_reg equ Ox8l
trisb equ Ox86
;----------------------------------------------------------
; bit equates
rpO equ 5
;==========================================================

Notice the include statement in the program listing (PICT25.ASM). Assembling PICT25.ASM
will include the file 16F84.INC.

Include statements may be in one of the following forms:

include "filename.ext"
or
include <filename.ext>
The include file must be in the current working directory (such as \PIC) at assembly time.

You may want to consider creating a complete include file of your own for the PICl6F84 that
contains:

CPU equates (memory map)


File registers
Bit equates
Option register
Status register
INTCON register

As an alternative, an include files for many of the PIC16s come with MPASM and MPLAB.
You will want to print out and examine the list of labels used in these files if you go this route.

150
I/O CONVERSION

INPUT CONVERSION

Input port lines must be able to clearly distinguish a "1" from a "0". If a signal is making a tran-
sition from LO to HI, the input port must see one or the other. The snap-action feature of the
schmitt trigger will solve this problem. The transition from LO to HI will be clean regardless of
how slowly the input is changing. Once switching has occurred, a large change in input voltage
is required to switch back.

~_--1~74~HC_1_4_--,
CMOS Compatible )~ __
Input port
Input
~----

The 74HC14 is a hex schmitt trigger inverter.

In a situation where the supply voltage for the input circuit is greater than 5 volts, a 2N7000
MOSFET (Motorola or Siliconix) may be used. A voltage divider on the input presents the
proper level to the gate of the MOSFET.

+5VDC

10K

Sensor
Input port
+6V Input >---.I'---+----i
OV

220K

.InQ!.!t.Y Output V
6V OV
3 - 3.6V Transition
OV 5V

151
If the input signal is not 5 volt CMOS compatible, some voltage level conversion and perhaps
some isolation may be required. An optocoupler will serve the purpose. It consists of an LED
on the input and a phototransistor on the output.

Base (N.C.)

5
Anode Collector

Cathode Emitter
2 4
3

N.C.

Since the coupling of output to input is via a light beam, electrical isolation of the output and
input is achieved. Optocouplers are rated in KV (isolation voltage). The 4N26 (Texas
Instruments) is readily available and offers the following specifications:

High voltage isolation 1.5 KV


Max collector-emitter voltage 30 V
Max emitter-base voltage 7 V
Max input diode continuous forward current 80 rnA

152
A simple application example might be sensing a switch closure in a 24 VDC system.

+5VDC
+24VDC - - /

4.7K
4N26

~ port Input
Open HIOr5V
Closed LOOr O.1V

153
OUTPUT CONVERSION

It is commonly necessary to drive loads larger than HCMOS output ports can handle. Various
devices can be used to boost the output of a port chip such as a transistor, MOSFET,
inverter/buffer; optocoupler or solid state relay. Another possibility is to Use a port chip with
greater drive capability built-in.

Except as noted, all circuits turn on the external component when the port pin is set to 1 or HI.

+60VDCMax

RL i I 2BOmA max

Output Port
I
.
Output Port 1----1
.
2N7000
MOSFET

+V

l\J Relay

Output Port IO~Ui II---~ Port RL

7406
Open collector, 30 VDC max,
sinks 30 rnA in output LO condition

+5VDC +V

3300 RL
4N26
,..-------....5
_t--+--.... Output

Output Port A 0 or low on the output port pin


2 1 - - - - - -........ causes current to flow through RL

154
The Sprague ULN-2803A Darlington array provides eight channel high voltage, high current
capability. The inputs are 5V TIUCMOS compatible while the outputs can handle 500 rnA
(max) at up to 50 volts (max). Each channel has an open-collector output (Darlington pair) with
an integral diode for inductive load transient suppression.

ULN-2803A Darlington Driver

Inputs Outputs

7 1 18 7
6 2 17 6
5 3 16 5
4 4 15 4
3 5 ULN-2803A 14 3
2 6 13 2
1 7 12 1
0 8 11 0
GND 9 10 Common Diode
Cathodes

Common Cathodes

Out
In

Output Port ULN-2803A Outputs

155
A variety of optocouplers are available for output conversion applications. The light activated
output component may be a transistor, Darlington transistor pair, field effect transistor, Schmitt
trigger, SCR or 1RIAC.

Solid state relays use optocouplers to provide control-to-load isolation. The output is connected
to a transistor for DC applications or to an SCR or TRIAC for AC applications. A variety of
solid state relays are available. Choose an HCMOS compatible input with output to suit the
application.

156
MORE PleIn BOOKS

PIC'n Up The Pace is an intermediate level applications guide. Serial communication as a


means of transferring data between PICI6s and peripheral chips and also between two or more
PICI6s is described. Use of the 93C46 serial EEPROM is detailed as an example. Since we live
in an analog world, ND and D/A are discussed with several methods illustrated for each.
Conditioning signals from sensors with an analog voltage output is described. Interfacing
PIC-controlled systems with humans requires some math, binary to decimal conversion and vice
versa, alphanumeric LCD interfacing and scanning keypads. Single wire serial communication
with a PIC-controlled LCD module which can be built by the reader is included. A digital
thermometer example project brings these topics together as an example. Finally, PICI6F84
data EEPROM memory, program memory paging and locating tables in program memory are
discussed.

PIC'n Techniques is also an intermediate level applications guide.

The book describes the unique features of the 8-pin microcontrollers.

The use of timer I, timer 2 and the capture/compare/PWM (CCP) module is detailed, followed
by timing, counting and pulse width modulation (PWM) experiments. These experiments
include producing a single time interval output, free running pulse output, event counting, time
measurement, frequency measurement and PWM. Some of these techniques are illustrated
further by experiments which show how to design and build simple digital pulse and frequency
generators and time interval and frequency measurement instruments.

The book also explains how to establish serial communication between a PIC chip and a PC via
a RS-232 conversion circuit and a terminal program. These techniques are used in a digital
voltmeter/data logger experiment for uploading data to a PC for display plus graphing using a
spreadsheet program.

PIC'n Up The Pace and PIC'n Techniques give the reader the tools to design and build
intermediate level microcontroller-based instrumentation and systems.

Serial P IC'n is a comprehensive advanced level book which details various methods for
implementing serial communications between a PIC microcontroller and an external device.
Asynchronous serial communications is covered both by using an on-chip USART and by bit-
bang methods. The RS-232 standard is explained. A discussion of synchronous serial
communications includes the PC (Philips Semiconductors), SPI (Motorola) and Microwire
(National Semiconductor) protocols. The Dallas Semiconductor I-Wire bus is described. Many
code examples are included as modules which will provide the basis for the reader's own PIC
microcontroller applications.

You may order these books from the distributor or store where you got this book or you may

157
order directly from:
PUBLISHER

Square 1 Electronics
P.O. Box 501
Kelseyville,CA 95451 U.S.A.

Voi ce (70 7)2 79-8881


FAX (707)2 79-8883
EMAIL sqone@pacific.net
http://www.sq-1.com

Secure on-line ordering is available.

We are also working on other Ple'n books. Our new offerings will be featured on our Web site
as they become available.

158
APPENDIX A
SOURCES

Following is a list of sources for PIC 16 parts, information and tools.

Digi-Key Corporation Parts/Programmers


701 Brooks Ave. South
Thief River Falls, MN 56 701-06 77 USA
(800)344-4539
http://www.digikey.com

DIY Electronics Programmers


P.O. Box 88458
Sham Shui PO Hong Kong
Int+ 852 2720-0255
Int+ 852 2725-0610 FAX
http://www.kitsrus.com

DonTronics SimmStick(tm) Protyping


P.O. Box 595 Boards for PIC16
Tullamarine 3043 Australia Programmers
Int+ 613 9338-6286
Int+ 613 9338-2935 FAX
http://www.dontronics.com

Elektronikladen Mikrocomputer GrnbH+CO.Kg. Programmers


W. Mellies Str. 88
32758 Detmold Germany
Int+ 49-(0)5232 8171
Int+ 49-(0)5232-86197 FAX
http://www.Elektronikladen.de

JDR Microdevices Parts/Programmers


1850 South 10th Street
San Jose, CA 95112-4108 USA
(800)538-5000

JAMECO Parts/Programmers
1355 Shoreway Road
Belmont, CA 94002-4100 USA
(800)831-4242
http://www.jameco.com

159
Marlin P. Jones Programmers
P.O. Box 12685
Lake Park FL 33403-0685 USA
(800) 652-6733

Microchip Technology Inc. Manufacturer of PIC16


2355 West Chandler Blvd.
Chandler, AZ 85224-6199 USA
(602) 786-7200
http://www.microchip .com

microEngineering Labs, Inc. Programmers, software


Box 7532 and prototyping PCB's
Colorado Springs, CO 80933 USA
(719) 520-5323
http://www.melabs.com

Milford House Programmers


120 High Street
South Milford
Leeds LS25 5AQ England
Int+ 44 1977 6836 65

Probyte Oy Programmers
Nirvankatu 31
33820 Tarnpere Finland
Int+ 358 3 2661885
Int+ 358 3 2661886 FAX

160
APPENDIX B
HEXADECIMAL NUMBERS

Binary numbers which are two bytes long are difficult to recognize, remember and write without
errors, so the hexadecimal numbering system is used instead. Think of hex as a kind of
shorthand notation to make life easier rather than some kind of terrible math.

Hexadecimal Binary Decimal

a 0000 a
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
A 1010 10
B 1011 11
C 1100 12
D 1101 13
E 1110 14
F 1111 15

Hexadecimal is the language used in this book. It will seem awkward at first, but working with
binary is time consuming and will result in errors which would quickly force you to learn
hexadecimal. Using hexadecimal is not difficult. All you need is a little practice.

One byte requires two hex digits. Note that the bits representing a byte are sometimes shown in
groups of four. Note, also, that the most significant binary digit is on the left.

Hex numbers are denoted by "Ox" in this book.

161
APPENDIX C
PROGRAM LISTINGS vs. PAGE NUMBER

pict1.asm 23
pict1.1st 31
pict2.asm 60
pict3.asm 62
pict5.asm 67
pict7.asm 114
pict8.asm 85
pict10.asm 74
pict11.asm 76
pict12.asm 81
pict13.asm 78
pict14.asm 92
pict15.asm 105
pict16.asm 117
pict17.asm 120
pict20.asm 123
pict21.asm 128
pict22.asm 64
pict24.asm 145
pict25.asm 149
pict54.asm 138

162

Vous aimerez peut-être aussi