|
PROGRAMMING
PIC CHIPS Part I
Page 13
INDEX
This chapter should be read AFTER you have done the experiments in the 5x7
Display project. It covers some of the things we have discussed already but
it is worth going over them again.
The 5x7 Display experiments show how to write a program and you can see
how instructions are laid out to produce sub-routines and how these are
combined to produce a program.
Our approach to writing a program is very linear. Many writers produce very
small sub-routines with GOTO’s from one sub-routine to another that produce
“jumps all over the place.”
The micro is perfectly capable of jumping up and down a program but this type
of layout is very difficult for the reader to follow.
With ours, it is much easier to follow the sequence of events and you will very
soon be able to write programs similar to those in the projects section.
The items you will need are:
1. The Library of Terms and Routines chapter,
2. The Instruction Sets for
PIC12C508A
and
PIC16F84
3. The Hex file at the back of this book,
4. Some or all of the following development tools:
18 Pin to 8 Pin adapter Type A
18 Pin to 8 Pin adapter Type B
5x7 Display for programming F84 chips
Pseudo 508A Module for developing a ‘508A program
Experimenter Board MkIII
PIC12c508A 6v Express Module
PIC16F84 Express Module
5. Any project with an 8-pin socket for a ‘508A chip.
WHERE DO I START?
The question you will be asking is: "Where do I start?"
This book is the starting point. It covers two of the smallest and simplest
microcontrollers in the PIC range, the 508A, and F84, and with our development
tools you can get into programming at the lowest cost.
The two micros are almost identical except for a couple of minor
differences. The ‘508A has 5 in/out lines and one input-only line, while the
F84 has 13 in/out lines. The ‘508A has 511 locations for a program while the
F84 has 1024 locations. But apart from that, if you follow our rules, you can
write a program that can be loaded into either device. There is one other small
difference. The ‘508A is a One Time Programmable device while the F84 can be
re-programmed up to 1,000 times.
There are differences between the two but to keep things simple, you can
consider the F84 to be about twice the size of the ‘508A.
If you follow this line, you will be able to glide from one device to the other
according to the complexity of the project.
Both microcontrollers have the same instruction-set (there are very minor
differences as shown on the two Instruction-Set pages at the back of this book)
and you only have to learn about 33-36 instructions to be able to create a
program.
These 33/36 instructions expand into more than 2,000 instructions when you
consider every bit in each file can be SET, CLEARed or TESTed, but you only
have to remember 33 “English-like” words (called mnemonics) to create a
program.
One of the advantages of the PIC range of microprocessors is the security
feature. It means the program you down-load into a chip cannot be read by
anyone else. At best they can only get a garbled set of figures.
A PIC microcontroller is similar to an exercise book - a book with blank
pages. It has an area where your program is placed. The program is created by
you and loaded into the chip via a device called a burner or programmer. We
have called ours: “Multi-Chip Programmer.”
As already mentioned in the introduction, we have worked out a way to allow
'508A programs to be developed without wasting any chips. It uses a module
called the Pseudo'508A.
The Pseudo'508 module allows you to write programs in stages and test them
in a Module called the 12c508A 6v Express.
The Pseudo'508A module is really an F84 wired so that it performs exactly
like a '508A and this means you can re-program it as many times as needed,
during the development of a program.
The F84 chip in the Pseudo ‘508A module is taken out and burnt on the “5x7
Display” project or “Multi-Chip Programmer."
Once you develop and perfect the program it can be burnt into a low-cost OTP
'508A, and fitted into a project you have developed, and YOU hold the key to
its operation.
That's why programming PICs can be a very rewarding venture.
"What Do I Need?"
To create a program for a '508A microcontroller, the items you need have
been listed above.
Programs can be written in an exercise book or on blank paper. From there
they are transferred to a Notepad program on your computer. Each line is
written in mnemonics, a half-English, half computer language that both you and
the compiler understands.
The program is then converted to Hexadecimal code via a program called MPASM.
This is available for downloading from this website.
The .hex file is sent to the microcontroller in the form of binary
1's and 0's to be “burnt” into memory.
Don't worry about the small programming space of 1FF locations for the
'508A. This is equal to over 500 lines of code and if you write 50 instructions
on a page of paper, this represents more than 10 pages! In reality, only about
255 locations can be used but this is still a fairly lengthy program.
One point to remember: - as you write and develop a program, it will consist
of many SUB-ROUTINES followed by a MAIN ROUTINE. These sub-routines will be
called one or many times. Thus, as a program gets longer, you may find you can
use sub-routines that have already been written and so your program becomes
more efficient.
THE ‘508A
These notes have been written for the ‘508A, however everything you write for
the ’508A can be instantly transferred to a PIC16F84.
It works this way. Suppose you are designing a project requiring one or two
input lines and two or three output lines. This is ideal for the ‘508A.
Suppose you are half-way through the project and realise you need an extra 7
output lines for a 7-segment display. The project is possibly too big for the
‘508A, but nothing is lost. All the code you have written will apply to the
F84. The reason is we are only suggesting you use instructions and files that
are common to both devices. All the files have the same names and the
input/output lines for the ’508A: GP0, GP1, GP2, GP3, GP4 and GP5 are changed
to RB0, RB1, RB2, RB3, RB4 and RB5.
It’s more difficult to go from an F84 to a ’508A but it’s not impossible.
Obviously it’s best to select the most suitable microcontroller in the first
place, but this course shows the interchangeability of the two devices.
HEX NOTATION
All the values in our programs are written
in Hex. This makes writing a program more complex but understanding hex gets
you one step closer to seeing how the program operates and allows you to work
out the values to make the individual port lines input or output.
The program values are loaded into a register called the working register (the
W register). These values are called LITERALS. A Literal is simply another name
for Value or Number.
The Hex code has a base of sixteen numbers and
these are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A = ten, B = eleven, C = twelve, D =
thirteen, E = fourteen, F = fifteen.
For instance, twelve is 0C and fifteen is 0F.
It's easy to see 3E is a hex value (equal to sixty-two), but to make it easy to
recognise hex values such as 23 or 41 or 82, a small "h" is placed
after the value thus: 23h, 41h, 82h.
A file is capable of holding a value from 00 to
FF and this represents a value from zero to two hundred and fifty-five in
decimal or ordinary numbers. See the page of Hex values from 00 to
1FF and look through them to see how Hex notation is structured.
It will take time to understand hex but while we
are here, there is another concept you must understand. It is: BINARY-TO-HEX.
The binary code consists of only two values
"0" and "1."
All the files in the '508A and F84 are made up
of 8 "cells" in which a "zero" or "one" is placed
in each cell. The 8 cells are separated into a group of 4 upper cells and 4
lower cells. The 4 upper cells are called the HIGH nibble and the 4 lower cells
are called the LOW nibble.
To read the complete (or total or full) Hex
value in a file, the HIGH nibble and LOW nibble are combined.
Each GP line (A GP line is a General Purpose
input/output line) corresponds to a bit in file 06. Line GP0 corresponds to the
Least Significant Bit (LSB) and GP1 corresponds to the next bit (bit1).
Now, here comes the hard bit to understand, but
it's logical.
To make GP0 an output line, the LSB in file 06
must be 0. "0" stands for Output.
To make GP0 an input line, the LSB in file 06
must be 1. "1" stands for Input.
Suppose you want to make GP0, GP1 and GP2 input.
The three low bits must be "1." This makes the file = 0000 0111 = 07.
Suppose you want to make GP3 input. The file
value will be = 0000 1000 = 08.
Suppose you want to make GP3 and GP5 input. The
file value will be 0010 1000 = 28h.
Any combination of lines can be input or
output and it's essential to understand hex notation to create the value to
load into file 06.
File 06 has only six functional bits but all the
other files contain 8 bits. You need to know hex when loading a file because
you may need to know: (a) when a certain bit is SET in a file being
incremented, or (b) the maximum a file can hold for a table, or (c) the output
pattern when a counter has been "clocked."
Binary values are involved in all stages of
program writing and hex is simply a short-form of showing the binary value,
using 2-digits. Hex is easy to see and easy to read. In addition, you can
mentally convert binary-to-hex and hex-to-binary very quickly.
THE FILES
The '508A contains thirty-two files or registers of which the first seven (00h
to 06h) are called Special Function Registers (SFR's) and the next twenty-five
(07h to 1Fh) are General Purpose Registers or Files (GPR's).
The F84 has twelve Special Function Register (SFR’s) (00h to 0Bh) and the
next sixty-eight (0Ch to 4Fh) are called “Files.”
Twenty files are common to both the ’508A and F84. They are: 0C, 0D, 0E, 0F,
10h, 11h, 12h, 13h, 14h, 15h, 16h, 17h, 18h, 19h, 1A, 1B, 1C, 1D, 1E, 1F. These
are the files we will be using.
Each file has 8 bits which can be made
"0" or "1." When all the bits are zero (0000 0000), the
file has a value of zero.
When the LSB is "1," the file has a
value of 1. We have already shown how the low nibble in the file increments to
F (see Hex Notation at beginning of article). The next increment after 0F
produces 0001 0000 = 10h, followed by 0001 0001 = 11h. The file increments to
1111 1111 = FF then "rolls over" to 0000 0000.
Before leaving hex, there's one more skill you
will need. It's converting binary to hex so you can SET bits in a file.
Setting single bits is easy. Here is the table:
0000 0001 = 01h = bit0
0000 0010 = 02h = bit1
0000 0100 = 04h = bit2
0000 1000 = 08h = bit3
0001 0000 = 10h = bit4
0010 0000 = 20h = bit5
0100 0000 = 40h = bit6
1000 0000 = 80h = bit7
To set TWO or MORE BITS in the high or low
nibble, read on. Remember, the lowest bit is called bit0 and the highest is
bit7.
To set bit2 and bit3, the binary value is: 0000
1100. From the table above we see this is 08h plus 04h. How do you add 08h and
04h together?
Simple. Take the highest value and ADD four
counts to it as follows:
oh nine, oh aye, oh bee, oh cee. The answer is
0Ch.
To set bit6, bit5 and bit4, the procedure is:
0111 000. This is 40h plus 20h plus 10h. We take the high nibble as 4h + 2h +
1h to make things simple. This is 7h and so the answer is 70h.
To set bit7, bit6, bit5 and bit4, the procedure
is: 1111 0000 = 80h + 40h + 20h + 10h. This is 8h + 4h + 2h + 1h (in the high
nibble). Start with 8 and increment it four counts thus: nine, aye, bee, cee.
Then increment it two counts: dee, eee. Then
increment it one count: "eff." The answer is F0.
It will take time to become proficient but work
on it.
THE WORKING REGISTER (W)
The Working register is the most important (most busy) register in the chip. It
operates like a basket in a super-market, picking up a value from the program,
such as a Literal, or a data byte from a table, a value from any of the files
or data bits from the input port and delivering it/them to another file, or the
output port. The output port is file 06 and any value delivered to this file
via W, is available for outputting.
It also works in reverse. Any value presented to this file from the outside
world is delivered to file 06 and from file 06 it can be passed to the working
register. The working register can be cleared (zeroed) or loaded with a number
(called a literal).
Bits in the working register cannot be tested,
cleared or set, or the nibbles swapped. It cannot be incremented, decremented
or the bits rotated. These operations have to be done on a value in a file.
The Working register is merely the
"carrier" or "helper" in the system.
It does not have an address location, it is
merely called "W" in an instruction.
THE DESIGNATOR
There are features in the PIC instruction set that make it "very
powerful." By this we mean a single instruction incorporates two or three
things. In the early microprocessors, an instruction did only one thing. That's
why you needed a lot of instructions in the instruction-set.
One of the clever features of the PIC
instruction-set is the designator. It's the number 1 or 0 added to the
instruction to tell the micro where to put the result of the operation.
If we take the instruction ANDWF 0C,1 the result
is placed in file 0C. If we use the instruction ANDWF 0C,0 the result is placed
in the W register. There is an obvious importance in selecting the correct
instruction as the first instruction changes the contents of file 0C while the
second instruction does not change 0C and we may not want 0C changed.
With some instructions it is more difficult to
see the purpose of the designator. For instance, MOVF 0C,1 merely moves the
contents of file 0C in and out of 0C and alters the flags. It DOES NOT put the
contents in W. To put the contents in W, the instruction MOVF 0C,0 must be
used.
When writing a program it is important to
include the designator. If you forget, the compiler (MPASM) will add a default
designator and report the condition.
You must check this as the fault designator may
not produce the required result. For instance:
MOVF 0C,1 does not put the contents of 0C in W -
it merely moves the contents in and out of 0C.
WRITING A PROGRAM
The program for a '508A starts at address
000 and extends to 1FF. This is a hexadecimal number and corresponds to 512
locations (512 lines of code). We can only use up to 511 address locations as
the top location is used by the micro as a calibration value. (OSCCAL).
For the applications are will be talking about (such as games, displays,
timers, counters, etc.), 511 lines of code is a good-size program especially
when you consider the chip is capable of taking the place of 5 or more standard
chips in a project.
Before writing a program, you should look through the projects we have included
in this book as well as the Library of Terms and Routines to get some idea of
what the micro can do.
This will also give you an idea of how the instructions are written and the
type of instruction required for a particular operation.
The easiest way to learn is by example and spending time with the projects and
looking through the routines in the Library will get you to the "starting
blocks."
Most of the thinking that goes into writing a program cannot be seen in the
final version of the project so let's find out what the programmer is thinking
when he produces a routine.
Firstly he has to work out what he wants the
project to do. He doesn't worry about the program or the micro for the moment.
He just thinks about what he wants to SEE the project do.
All the timing, pin numbers, LED colours and
types of sounds will come later.
Firstly produce an overall description in the
form of an essay, set of notes or a flow diagram.
FLOW CHARTS AND FLOW DIAGRAMS
Some schools of thought think a flow chart is
essential for successful programming.
If you are not up with flow-chart symbols or how
to produce such a chart, don't worry. Other schools consider them to be
absolutely un-necessary!
For those who are keen, there are only three
flowchart symbols you need to know.
They are the start and stop ovals, the rectangle
in which an operation is performed and the decision diamond where a
"yes" or "no," "on" or "off," decision
is made.
These shapes are connected with lines and the
arrows indicate the direction of flow of the program.
A flowchart helps others to understand what the
program is doing and gives an idea of its complexity.
The best way of starting a new project is to
write a description of the entire operation. Then separate it into sections and
place each step in an "operations" rectangle. Any decision-making
stages are placed in a diamond then linked with lines and arrows and - hey
presto! You have produced your own flow chart!
Next take each section and convert it into steps
that can be carried out by the microcontroller. This is where knowledge of
programming comes in. To do this you need to understand the instruction-set so
you can write the correct instructions.
It is also very important to put them in the
correct order so the outcome is exactly as you intend.
THE SIMPLEST PROGRAM
The simplest program will load the working register with the value
"1" and output it to GP0.
If a LED (in series with a 470R to 2k2 resistor)
is connected to GP0, it will illuminate when this instruction is executed.
But before we can run this very simple program,
we have to "set-up" the port so that GP0 is an output.
So, lets' go back to the start.
THE SIMPLEST PROGRAM: |
SetUp
|
MOVLW 3E |
;GP0 output, GP3 input |
|
TRIS 06 |
;Load TRISB file |
Out0
|
MOVLW 01 |
;Load W with 1 |
|
MOVWF 06h |
;Make GP0 HIGH |
|
GOTO Out0 |
|
GP0 is one of the input/output lines of the
chip. Before a program can output a value on this line,
the port must be "set up" so that GP0
is an output. GP0 is bit0 of the TRIS register and it must be "0" to
be an output. The other bits can be anything. We will make them "1"
(input) to highlight the fact that the '508A port has only 6 lines. Thus the
TRIS register will be: 0011 1110 = 3Eh
Since we are using the Pseudo'508A for program
development, the instructions for "set-up" are as follows:
SetUp
|
MOVLW 3E |
;Make GP0 output |
|
TRIS 06h |
;Load TRISB file |
GP0 is now an output line. It will deliver a
HIGH to the outside world when "1" is loaded into bit0 of file 06.
The instructions for this are:
MOVLW 01 |
;Load W with 1 |
MOVWF 06h |
;Move W to file 06 |
The GP0 line will produce a HIGH and a LED
connected to this line will illuminate when the above two instructions plus the
set-up instructions are executed.
When this program is loaded into a chip on the
Pseudo'508 module , you can think of an imaginary pointer starting at the first
instruction and passing it to the central processing unit for execution.
The "pointer" is the Program Counter
(PC). It starts at 000 and increments one location at a time and feeds the code
(at the address) to the central processing unit where it is acted upon.
Once the micro is set into operation, it does
not stop. It continues down the program.
In the program above, the Program Counter will
"run off the end of the program." To prevent this from happening,
additional instructions are needed to "guide" the program counter.
The complete program is shown above.
The first 06h in the program is not the port
file. It is the TRISB register. The second 06h is the input/output port.
The GOTO instruction creates a loop to make the
micro go to the "Out0" label.
Once the micro enters this loop, it never comes
out, unless the power is switched off.
IN ENGLISH!
Let's explain the "Simplest Program" in English!
The instructions to make the LSB in the TRIS register an output are:
MOVLW 3E |
; Put 0011 1110 into W to make GP0 an
output |
TRIS 06 |
|
The binary value 0011 1110 shows bits 6 and 7
are not needed as the '508A has only 6 port lines and all the other lines will
be input lines (as shown by the value "1") except the lowest bit,
which will be an output. In other words we only have to make bit0 a zero!
The value in W is moved into the TRIS register
and this will make the Least Significant Bit in TRIS an output. The port is now
set up with the LSB (least significant line) an output. This line is called GP0
(General Purpose in/out line 0).
Line 3 moves (loads) W with 1: |
|
|
MOVLW 01 |
;Load W with 1 |
|
MOVWF 06 |
;Move W to the port file |
|
The instruction in line 5: |
|
|
GOTO Out0 |
|
tells the micro to go to the label Out0 at line
3 and the micro executes a loop of lines 3, 4 and 5. This is called an ENDLESS
loop as the micro will continue to execute these three instructions until the
power is removed.
.ASM
Programs are written using the 33/36 PIC
instructions on a Notepad program and saved with the extension .asm (dot ASM).
When a program is written as shown in the "Simplest Program," it is
called ASSEMBLER CODE and saved with the extension .asm
In other words it is written for an assembler.
The assembler we use is called MPASM and it will locate all the tags and labels
and convert them to an address and convert the instructions to Machine Code.
The result is a file with the extension .hex
THE NEXT SIMPLEST PROGRAM
To add to our simplest program, we can
include a push button.
The button has been added to the circuit so that when it is pressed, GP3 sees a
HIGH. This is called POSITIVE LOGIC.
The program is now required to "turn on a
LED when a button is pressed." This statement must be converted into a set
of instructions that can be executed by the '508A.
The program needs to be in the form of a loop so
the button can be detected when pressed and the LED turned on. When the button
is released, the LED must turn off.
THE NEXT SIMPLEST PROGRAM: |
|
MOVLW 3E |
|
|
TRIS 06 |
;GP0 output, GP3 input |
Sw
|
BTFSS 06,3 |
;Test GP3 |
|
GOTO Released |
|
|
GOTO Pushed |
|
Pushed |
BSF 06,0 |
;Make GP0
HIGH |
|
GOTO Sw |
|
Released
|
BCF 06,0 |
;Make GP0 LOW |
|
GOTO Sw |
|
All programs from now on consist of a LOOP. The
simplest program above is the only program using a "dead-end" loop.
A normal program is in the form of a complete
FUNCTIONAL loop, and since the micro is executing instructions at the rate of
approximately one million per second, the loop will be executed many times per
second.
The instructions in the loop must include
looking at the switch to see if it is pressed or not pressed and outputting a
HIGH or LOW on a line to turn the LED ON or OFF.
Set up the TRIS register so that GP0 is an
output and GP3 is an input. This is the same as for the simplest program.
|
MOVLW 3E |
;GP0 output, GP3 input |
|
|
TRIS 06 |
|
|
|
The next instruction looks at the switch on GP3.
The instruction is: |
|
Sw
|
BTFSS 06,3 |
;Test GP3 |
|
The instruction above tests bit 3 of file 06
(the port file). The micro "reads" the port and tests bit 3 to see if
it is SET (HIGH).
The micro will jump (i.e. skip or NOT CARRY OUT)
the next instruction in the program if the bit is SET. When the switch is
pressed, the line will be HIGH and bit 3 will be SET. If the bit is SET - the switch is
pressed, the micro will execute the
instruction GOTO Pushed.
The next two instructions are:
|
GOTO Released |
|
|
GOTO
Pushed |
|
We have created two branches in the program. The
Released branch (for not pressed) and the Pushed branch (for switch pressed).
If the bit is SET, the switch will be pressed. The instructions for the "Set" mini-routine are: Make GP0
HIGH then go to "Sw" to look at the input:
Pushed
|
BSF 06,0 |
;Make GP0
HIGH |
|
GOTO Sw |
|
If the bit is Clear, it will be LOW and thus the
switch will not be pressed. We now need to produce one or more instructions for the
mini-routine "Clear." The instructions for "Clear" will
clear bit0 of the port so that line GP0 is LOW and the LED will turn off.
|
Released
|
BCF 06,0 |
;Make GP0 LOW |
The micro must now be sent back to test the port
again to see the condition of the switch. The instruction is:
The program is constantly looping (polling) the
instruction to look at the switch and turn the LED on or off.
FLASHING A LED
If you want to make the LED turn on and off
automatically, a different set of instructions are needed.
Firstly you need instructions to turn the LED
on, then a routine to keep it on for a period of time (this is called a DELAY
routine), then instructions to turn the LED off and finally a delay routine.
The program must then loop back to where the LED
is turned on. The result is a flashing LED.
A flow chart can be produced for this sequence
using the symbols shown previously.
This will help to show the number of steps
involved in the program.
From the flow chart we can produce a layout for
the program:
SetUp
|
- - - - - |
Set-up instructions go here |
|
- - - - - |
Set-up instructions go here |
|
GOTO Main |
|
|
Delay
|
- - - - - |
Delay instructions go here |
|
- - - - - |
Delay instructions go here |
|
RETLW 00 |
|
|
Main
|
- - - - - |
Turn on LED
instructions go here |
|
- - - - - |
|
|
CALL Delay |
|
|
- - - - - |
Turn off LED
instructions go here |
|
- - - - - |
Turn off LED
instructions go here |
|
CALL Delay |
|
|
GOTO Main |
|
NEXT
|