PIC Tutorial
PIC Tutorial
This tutorial
serves as guide for absolute beginner to microprocessor. No
programming or electrical experience needed to complete
understand this tutorial. This text will guild you to the most basic
program in controlling the processor such as turn on LEDs at output
port, read from an input port, timing control for this type of
processor. We will look into example that turn the LEDs on the
processor on and off at a specified time rate. This tutorial will give
you the most basic library of codes that are useful and can be further manipulate in your
future more advance project with PIC Microprocessors
The world of technology is advancing in a faster pace each day. Our common use tools have entered a
digital phase where everything is computerized. From analog phone, we evolved to digital phone. In
automobile industry, we have on board microprocessor to control fuel injection. Motivated by this
great technology evolution, this tutorial will act as your introduction course to the basic of
microprocessor.
You need not to have any background in microprocessor nor how to build a rocket to understand this
tutorial. You only need the desire to learn, some time in your hand and the will to read through my
lack of English Grammar writing and also some parts below.
Ports
The PIC 16F84 has two ports; each can be
individually program as input or output.
PortA is a 5bits/lines (mostly use as input),
and portB is 8 bits/lines (normally use as
output). You can think of the PIC controller
as a fish tank with all the water lines running
in and out from it. Some of the line you will
hook up to the water coming in, the other for
water coming out. Remember, don’t mistake
the port as a single line; the two ports are each consists of multiple lines that can be use for
parallel data transfer.
Introduction to Architecture of PIC 16’
The PIC ’84 has two separate blocks of memory; Program memory and file registers
memory.
Program memory:
PIC’84 is 14 bits and can contain 1K of code. This is important to know because you don’t
want to write a lengthy program or put to much comment on to a program and it will not fit
into the PIC.
File Registers:
you can think of this as drawer in a cabinets. Some of the drawers are reserved for special
purposes. These register are located at reserve address that the designed for the PIC to
recognize and have higher priority then other address when it comes to interrupt (Read on).
Below are the most basic ones
Hex Name Description
Address
0x00 Indirect Indirect Address Pointer
Address
01 TMR0 Timer/Counter
02 PCL Program counter
03 Status Status Registers-Flags
04 Files select Indirect Pointer
05 Port A Data Port A
06 Port B data Port B
07
08
09
0A PCLATH Program counter Latch High
Order 5 Bits
0B INTCON Interrupt Control
Source: “Easy Pic’n”, David Benson, p.10
In this section, I only emphasize on the important features that are necessarily to better
understand this tutorial. For a more detail explanation, I suggest the book “Easy Pic’n” by
David Benson
Working register: ***This concept is important*****
Picture this; you can only open one drawer of the cabinet at a time. Therefore, to copy and
transfer some thing from one drawer to another, you need to have a temporary space to
dump data to. To move a shirt from drawer #1 to drawer #3. We do this; open drawer #1,
move shirt from drawer #1 to working register, close drawer #1, open drawer #3, move
shirt from working register to drawer #3, close drawer #3.
This is the only way to move data around the PIC’s registers.
Program Counter:
PIC controller, like many other controller; it’s execute code line by line. Let say the PIC
execute line #1. How does it know to go to line #2 or jump to a section after a “goto”
instruction? Well the Program counter get updated every line after the PIC goes through a
line of code. It’s keep track of which part of the program to jump to next.
Status Register:
Status register keep record of result of operation. Two important items are Zero flag and
Carry flag. Imagine this; you subtract decimal base number 5 to number 5. The result is
zero. The Status register have a bit that get set to 1 if the result is Zero from any operation
has just performed by the controller. Similar with the Carry bit. It detect if there is a carry
after an operation. I will emphasize this better in the Programming section.
To Top of Page
DIP Switch Circuit
An eight position DIP switch is interfaced to Port A (3 of the DIP's
switches aren't used). This is equivalent to PortA 0, 1, 2, 3, 4; You
can set them on or off easily with the switch.
The circuit’s lay out is not important; but try to arrange everything
is a neat design. This will give you less headache to trace any error
in wiring or lose connections. If you are thinking of future
expansion of the board, build the I/O node connection such that you
can easily tap into the input or output to for additional circuit
expansion.
LEDs
Eight LEDs hook up to Port B. The eight LED will response to the output from PortB
corresponded to your program.
Programming preparation
You will need a text editor to write you code with. The best one is using a note pad that come
with every Microsoft window Operating System. Just make sure that when you save it; save it
under “*.asm” extension (Choose “Save As”, and Save As Type should be set to “All Files”).
Then to convert the files from “*.asm” to “*.Hex” you can use MPASM v02.15/ or from
microchip to convert your files.
To burn the “*.Hex” to the chip, you can use PiccallW Programmer/ or from PICALL.com. I
use the Picall v0.14a beta and have problem trying to burn the chip. I was able to do it with
v0.10d. It’s up to you, if you think you can make it work…then use which ever version you
like. But it v0.10 you have to manually check 378 in LPT port in Setting. Then in hardware
setting, chose the appropriate kit that comes with your programmer. Mine was a 74LS06 (the
name of a chip on the programmer).
So the steps are:
Write the program, compile it into Hex, then burn it into the chip. Then, well feel the
sense of accomplishment when you LEDs start to light up the way you want it. :o)
Example 1:
;---------------------------------------------------------------------
; FILE: helloLed.asm
; AUTH: P.Oh
; DATE: 1.0 - 04/13/02 15:09
; DESC: 1.0 - Makes B0,B2,B4,B6 LO and B1,B3,B5,B7 HI
; NOTE: Tested on PIC16F84-04/P.
; Page numbers in code are in Easy Pic'n book
; REFs: Easy Pic'n p. 23 (Predko p. 173 is bogus?)
;----------------------------------------------------------------------
list p=16F84
radix hex
;----------------------------------------------------------------------
; cpu equates (memory map)
myPortB equ 0x06 ; (p. 10 defines port address)
;----------------------------------------------------------------------
org 0x000
start movlw 0x00 ;load W with 0x00 make port B output (p. 45)
tris myPortB ;copy W tristate, port B outputs (p. 58)
movlw b'10101010' ; load W with bit pattern (p. 45)
movwf myPortB ;load myPortB with contents of W (p. 45)
circle goto circle ; done
end
;----------------------------------------------------------------------
; at blast time, select:
; memory uprotected
; watchdog timer disabled
; standard crystal (4 MHz)
; power-up timer on
;---------------------------------------------------------------------
Code’s cheat-sheet
Move Data Description Example
MOVLW Move Literal into Working Register MOVLW b’00000001’
MOVF f,d Moves copy of selected File MOVF porta,w
Register contents into W or f
Movwf f Move contents of Working into MOVWF portb
Files Register
Change Register Contents
CLRF f Clear a selected File Register to 0. CLRF count
CLRW Clear Working register to 0.
COMF f,d Complement Files Register. All 1’s COMF temp,f
to 0’s and vice versa. Result in W or (invert all data in temp and
Files register save back into temp)
DECF f,d Decrement File Register; when DECF count, f
contest of register is 0x00,
automatically reset to 0xff. Result in
w or file register
INCF f,d Reverse of DECF
BCF f,b Bits Clear File Register, Clear a BCF portb,2
selected bit in register to 0
BSF f,b Reverse of BCF, turn a bit to 1 BSF portb,2
GOTO k Go to a specified address GOTO start
CALL k Call a subroutine at specified CALL delay
starting address
RETURN Return from subroutine
RETLW k Return from a subroutine and load RETLW b’00000110’
Working Register with literal
BTFSC f,b Bit Test File Register Skip next line Loop BTFSC porta,2
if Clear Goto loop
(this loop is on as long as line
2 of porta is a 1)
BTFSS f,b Bit Test File Register Skip next line Loop BTFSS porta,3
if Set Goto loop
(this loop is on as long as line
3 of porta is a 0)
DECFSZ f,d Decrements a File Register, Skip DECFSZ count,f
next line if contents equal Zero.
Result in File Register or Working
Register
INCFSZ f,d Increment a File Register, Skip next INCFSZ count,f
line if the contents Equal Zero.
Result in File Register or Working
Register
For more instructions, refer to page 46 of “Easy Pic’n”
Subroutines
………………………
………………………
call pause
………………………
………………………
pause movlw 0xff ; set w = 255 decimal
movwf mCount ; mCount = w
loadN movlw 0xff ; set w = 255 decimal
movwf nCount ; nCount = w
decN decfsz nCount, f ; nCount--
goto decN ; if nCount != 0 then repeat nCount--
decfsz mCount, f ; else decrement Count
goto loadN ; if mCount != 0 then
; reload nCount to 255 and decrement
return ; else exit subroutine
This example illustrates how you would call a subroutine during program execution. For
those who are not familiar with subroutine, think of it as stopping in the middle of lunch to
get a soda and then come back to eat your sandwich. During the process, you temporary stop
eating the sandwich to get the soda for this we use “call [label or address here]” to jump to
the address that the code of subroutine is written. But you have to get back the right point
where you have stop eating for this you will use “return” to return to we the program was left
of.
We can also use “retlw k” to return from a subroutine and automatically
load Working Register with a constant
Example 2: This program call return_literal.asm
;--------------------------------------------------
; This program add an offset to a specified register
; and return a predefine value at that address
;--------------------------------------------------
list p=16f84
radix hex
;--------------------------------------------------
org 0x00
Start molw 0x00 ;load w with $00
tris portb ;teach port B all outpts
clrf portb ;clear all line on portb to low
char molw 0x02 ;test number
call seg ;call subroutine
movwf portb ;Display result
again goto again ;done
seg addwf pc,f ;add w to PC, result in PC
retlw 0x3f ;0 seven segment
retlw 0x06 ;
retlw 0x5b ; The value return are what ever that you are controlling
; If you hook this up to a 7 segment display. Then depends on
; your connections, you will turn on the appropriate bits.
…………………………………………
…………………………………………
…………………………………………
end
;----------------------------------------------------------
; at blast time, select:
; memory uprotected
; watchdog timer disabled
; standard crystal (4 MHz)
; power-up timer on
;-----------------------------------------------------------
Time control
Example 1's LED/DIP circuit can be used to experiment with timing routines. The
programming objective is to blink the LED attached to line RB0 on Port B every 32.8
milliseconds. The ASM code follows:
Practice good programming style:
Be sure to use appropriate comments to describe your code.
Example
Molw b’00000001’ ;Turn on line zero of portb
Movwf portb
Well it is obvious that it will make line zero high. But we might want to say, turn on led
or buzzer. That way, we don’t have to trace back what line Zero really turns on.
Timing awareness is important. Let say you want to keep on polling line 0 of porta for
detecting people enter a room. Let say the first person enter the room. Then you want
your code to jump to a location to execute certain steps. Keep in mind that you don’t
want to make these codes too lengthy (too much time to execute) because you might not
get back to the polling process before the second person enter the room. Therefore your
program will not be efficient.
To Top of Page