Introduction
This book is a collection of useful program routines and examples written
in Parallax assembly language for the PIC 16C5x series of microcontrollers.
With minor changes, these routines may be adapted to the entire PIC 16Cxx
series.
The routines are based on the instruction set of the BASIC Stamp ®,
a PIC-based single-board microcontroller. A PIC on the Stamp circuit board
is programmed with a BASIC interpreter. The PIC reads instructions and
data stored in an EEPROM and interprets them to execute control programs.
The Stamp's version of BASIC, known as PBASIC, includes high-level instructions
for common control tasks, such as serially sending and receiving data,
debouncing pushbuttons, measuring and generating pulses, reading a potentiometer,
and producing sound. The routines in this book are clones of those PBASIC
commands that (in most cases) function the same way.
There are three audiences for this book:
-
BASIC Stamp users who want to program the PIC directly in Parallax assembly
language, but don't want to leave familiar programming methods behind.
-
PIC programmers who are looking for a cookbook of routines to speed program
development.
-
PIC programmers who see advantages in prototyping with the Stamp interpreter
before moving to the PIC for the final product.
Whichever group you belong to, there are a few prerequisites to using this
book effectively. You should have the Microchip and Parallax literature
on the PIC hardware and not be afraid to use it. This book is not padded
with the manufacturers' data sheets and instructions.
You should be comfortable with the terminology of digital logic and
microcontrollers. I'm not going to be shy about using standard abbreviations
(such as EEPROM, mA, µs) or computer-science terms (such as bit,
byte, loop, hex, binary, AND, OR, XOR). You should also know a little BASIC,
since most program structure is explained in terms of PBASIC. Finally,
you should have the Parallax assembler software and manuals. You may use
programming hardware from other vendors, but the Parallax assembler is
required to use these routines.
This book is not a disassembly of the PBASIC interpreter. That's proprietary
to Parallax, who would be crazy to give it away. Besides, it includes overhead
code to make the language work properly, and upon which each of the commands
depends. This would limit the usefulness of a disassembly as a toolkit
of standalone routines.
Differences from PBASIC.
These routines were developed by examining what each of the PBASIC instructions
does, and then writing assembly code to duplicate its function. In some
cases, functionality has been changed slightly to better suit the needs
of assembly-language programmers.
Manipulation of the Data-Direction Register.
Some of PBASIC's I/O instructions automatically change a pin's data direction
when they execute and then restore it when they are done. The PBASIC environment
permits this by keeping a copy of the PIC's tristate (TRIS) register in
normal read/write memory. The routines in this book do not work that way.
Comments tell you how TRIS should be set up, but the routines do not modify
it directly. This avoids causing mysterious bugs as a result of improper
TRIS bookkeeping outside the routines. It also keeps the routines small,
since many programs do not require any TRIS trickery.
Pin and Port Independence (PPI).
This is one of the great features of the BASIC Stamp--the ability to apply
any I/O command to any pin of the Stamp's single I/O port. This goes hand-in-hand
with the TRIS manipulations discussed above. All of the I/O routines in
this book follow this convention by letting you specify which pin and port
to use. Because they don't modify TRIS, it is your program's responsibility
to set the port pins to input or output as appropriate.
Many PIC applications use a particular I/O pin for only one or two purposes,
and can do without the overhead required to implement pin and port independence
(PPI). Although most of the program listings in the book use PPI techniques,
the accompanying disk contains non-PPI versions of some of the longer I/O
routines.
Merging Routines.
To use the routines presented here, you'll need to merge them, either with
each other, or with your own code. This is a straightforward cut-and-paste
operation, but can require a little thought and planning. Here are a few
hints:
-
Get the main body of your program working before merging other code into
it. Then, as you introduce pieces of the new code, retest your program.
If it fails, the problem is related to the new code. Knowing this fact
can simplify troubleshooting: look for conflicting uses of variables (especially
w), changes in the initialization of the TRIS (!ra, !rb...) registers,
and actions that could alter the status bits like c and z. Check the cheat
sheet in the appendix for possible side effects of your code.
-
Watch out for possible conflicts between buffers (such as those used by
Serin and Serout) and your variables. For example, the 16C55 has only 24
usable bytes of RAM beyond the special-function registers. If your program
uses five variables and you tell Serin to buffer 20 characters, you'll
overwrite the variable stored highest in RAM.
-
Work in steps. Merge and debug one routine before adding another. If you
run low on variables, look for opportunities to consolidate them. Throughout
these routines, variables that have names beginning with temp may safely
be used as temporary counters or workspace in other routines.
-
If a routine requires data to be passed via the w register, don't put other
code between it and call. Most of the Parallax macroinstructions use w
for something, and they'll alter the data that you meant to send to the
routine. Check the cheat sheet in the appendix.
-
Use the PSIM simulator. It can help trace problems--especially those involving
timing, status flags, and variable usage--that would be almost impossible
to find otherwise.
-
Use your head. For most people, assembly-language programming requires
great concentration, and assembly-language debugging requires even more.
Take it easy on yourself. If you run into a brick-wall problem, walk away
from it for a while. This advice sounds trite, but your subconscious will
continue to work on the problem, and will often present you with the answer
(or at least an alternative approach to finding the answer) after a good
night's sleep.
Structure of the Routines.
Most of the code presented in this book is in the form of callable subroutines.
While this makes it easy to incorporate the routines into your PIC programs,
it also makes it likely that you'll run into two limitations of the PIC
architecture; restriction of call destinations to the first half of program-memory
pages, and the two-level stack.
When the PIC executes a call, it clears bit 8 of the program counter.
This means that if you attempt to call code stored at address 256, you'll
end up at address 0 instead. The Parallax assembler won't allow you to
make this error; it will halt assembly and supply the line number of the
offending call.
If you use more than a few of these routines in your program,
you will very quickly fill the lower 256 words of a program-memory page.
What can you do if you run out of lower-half-page code space?
Start by examining the routines you're using and seeing which can be
converted to straight-line code. That means inserting them into the body
of your program where the call would normally be. Remove any returns (ret)
and replace them with jumps (jmp) to appropriate points in your code.
Also, examine the routines and try to strip out code that's not required
for your purposes. For example, some of these routines start out by converting
timing values to their two's complement. You could save overhead by precomputing
these values or consolidating the code that does the conversion.
One last technique is "call forwarding." Put the subroutine label and
a jump (jmp) instruction in the lower half of the page. Locate the real
guts of the routine, complete with the return (ret) in the upper half of
the page. Calling the routine sends program execution to the jmp instruction,
which redirects it to the actual subroutine, located elsewhere. This can
save your bacon when you need one more subroutine.
Using this Book with Non-Parallax Tools.
I feel that Parallax assembly language is clearer and more productive than
the original Microchip dialect. That's why I use it in my programming,
and why I used it to write this book. However, many of you have other PIC
tools--most notably the PICStart 16B from Microchip. You can use the Parallax
assembler PASM to assemble code for use with these tools. Just add the
switch /S after the file name. This suppresses the generation of Parallax-specific
configurat ion data (device type, wdt, oscillator, and code-protection
settings). PICStart doesn't accept this data. To assemble Serin for a non-Parallax
programmer, you'd type:
PASM SERIN /S
If you forget to use the /S, you'll get an address-out-of-range message
from your programming software. If you use the /S switch and still get
an error message, check the device type in the assembly-language source
listing. It may be set for a PIC with more program memory than the one
you're programming. For example, the device directive says "16C56" when
you are programming a 16C54. If that's the case, evaluate the program to
determine whether it will work in a '54. If it will, change the device
directive, reassemble the code, and try again.
Send us a message
Copyright © 1996-2001 DonTronics