Introduction to PIC 16F84 Microcontroller

Keywords: 16f84, pic tutorial, pic microcontroller, microchip controller, PIC16F84, Hello World, LED, DIP, timer, serial port, RS232, C programming

The photo depicts a PIC 16F84 microprocessor. 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.

Motivation and Audience

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.

·        The rest of the tutorial is presented as follows:

·        Parts List and Sources

·        Introduction to 16F84 Microprocessor

·        Building the Circuit

·        Programming Preparation

·        Induction to microprocessor programming

·        Some programming example

·        Final Words

Parts List

US-based vendors include Jameco, Digikey, JDR and Radio Shack . Note: Boondog has no association with these vendors. Attempts were acquire all parts from a single vendor. Part numbers for common resistors are not given.





PRICE (2002)



























0.1 UF CAP



1.00 FOR BAG OF 10















































Introduction to PIC 16F84 Microcontroller

This tutorial will walk a beginner to Microcontroller through the basic principle of the PIC family Microcontroller. Mainly focus on the 16F84 just simply because it’s simpler than other type to understand. For those who don’t know what a Microcontroller is; It is a brain of a digital device that operates in a close loop control process. It has I/O port to take in interrupt or data and send out signal to control relay or just simply a motor or that type of mechanisms.

The close up of a Microcontroller

Pins and it’s functions

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 portBis 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.

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.

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 Address




Indirect Address

Indirect Address Pointer






Program counter



Status Registers-Flags


Files select

Indirect Pointer


Port A Data

Port A


Port B data

Port B












Program counter Latch High Order 5 Bits



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.

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.

Building the circuit

This circuit helps to develop a sense of data flow within a PIC controller. It’s simply let you controller the I/O of the PIC to turn on a LED at portB, or scan for an interrupt at portA.

The Part

Zip Socket

Repeated burn-and-drops during development often require removing and re-inserting the PIC16F84. A zero-insertion-force (ZIF) socket eliminates the risk of accidentally bending the PIC's pins with an IC pulling tool. By releasing the ZIF socket's lever, the chip is easily removed by hand. Closing the lever securely fixes the chip in the socket.

Solder directly to PCB or plug directly into IC socket ,Screw mounting holes for reliable operation  Accepts .300" to .600" IC centers x .1" spacing  Weight: 0.1 lbs.

 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.


Eight LEDs hook up to Port B. The eight LED will response to the output from PortB corresponded to your program.


Tips to better and cleaner soldering.

Link to pdf files on cleaner soldering technique: soldering.pdf

After building the Hardware

Testing the circuit with out the PIC. Power up the circuit with a 5 Volt source. Use a multimeter and check for continuity in every wire that you use. Turn the Dip Switch on and measure the voltage across it. Run a wire from the positive of the source to pin 6-13 of the Zip pocket; the LEDs suppose to light up. And make sure you connect the clock appropriately.

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












You can use PiccallW Programmer . 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)

The PIC16F84 device programmer(PIC16PRO40)

For simplicity, we use the PicPro Programmer

******************************BE CAREFUL**************************

Do not try to remove the chip from the programmer by your thumb. This is a very idiotic way to break the chip’s pin. Trust me…I was there. Use a chip extractor or a flat head screw driver and carefully remove it ….

Program the PIC

For those who have a little background on programming, you should be able to understand this section after a careful review and you will be able to start programming on your own. And for those who already have experience in assembly language, this will just be a review for you. Let’s get started Assembly language

Program Structure

Comments:Explain the purpose of the program, type of chip, clock type and frequency, Date and author’s name, etc…Be descriptive about program but not too lengthy.

Header: Header contain instruction information of the type of chip and the base of number system
            list      p=16f84
            radix     hex
Initialization:Here, you define ports, variables
porta    equ      0x05
portb    equ       0x06
The above code tell the chip that “porta” is define at Hex address 05 and “portb” at 06 Program: You insert your program codes here


Start   movlw    0xff    ;load w(working register)with 0xff
            tris         portb ;teach porta to be an input
            movlw   0x00  ;
            tris         portb ;

Even though most books do this in the program section. I prefer initialize the port in the Initialization section.

End: The “end” statement tell the assembler that this is the end of the program

The symbol “;” will tell the assembler to ignore everything after it on that particular line

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
                  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
; at blast time, select: memory uprotected, watchdog timer disabled, standard crystal (4 MHz), power-up timer on;

Cheat Sheet

Move Data




Move Literal into Working Register

MOVLW    b’00000001’

MOVF                        f,d

Moves copy of selected File Register contents into W or f

MOVF            porta,w

Movwf                       f

Move contents of Working into Files Register

MOVWF    portb

Change Register Contents



CLRF                          f

Clear a selected File Register to 0.

CLRF              count


Clear Working register to 0.


COMF                        f,d

Complement Files Register. All 1’s to 0’s and vice versa. Result in W or Files register

COMF            temp,f


DECF                          f,d

Decrement File Register;  when contest of register is 0x00, automatically reset to 0xff. Result in w or file register

DECF          count, f

INCF                           f,d

Reverse of DECF


BCF                            f,b

Bits Clear File Register, Clear a selected bit in register to 0

BCF                portb,2

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 starting address

CALL             delay


Return from subroutine


RETLW                      k

Return from a subroutine and load Working Register with literal

RETLW      b’00000110’

BTFSC                        f,b

Bit Test File Register Skip next line if Clear


BTFSS                        f,b

Bit Test File Register Skip next line if Set


DECFSZ                 f,d

Decrements a File Register, Skip next line if contents equal Zero. Result in File Register or Working Register

DECFSZ     count,f

INCFSZ                f,d

Increment a File Register, Skip next line if the contents Equal Zero. Result in File Register or Working Register

INCFSZ      count,f

For more instructions, refer to page 46 of  “Easy Pic’n”

Some useful algorithms 

Data’s transfer

Remember, you need to use the working register to move data around. This example show how to display count register to portb in binary

            movf     count,w

            movwf  portb  

Data’s Direction

This instruction define the port to be input or output, a Zero is equivalent to output, 1 is input.

movlw b’00000000’        ;portb, all lines make output

movwf portb 

movlw  b’11111111’        ;porta, all lines make input

movwf porta 

Port Read/Write

To read from a port, you would move the content of that port into Working Register first. 

Movf    porta, w    ;Read line in from porta

Movwf temp         ;Store it into temp space 

To write out to output port, just simply copy Working Register to that defined port’s name 

movwf portb 

Loop, Using Counter to control loop

In this example, we are making line 0 of porta as a start button, and line 1 is the stop button. We want to detect both button and execute the appropriate process depend on which one was execute. 

Loop    btfss        porta,0   ;Detect button press

            goto         chkb          ;If not, check b

            goto         int          ;If yes, goto start interupt        

chkb     btfss        porta,1

            goto         loop                        

            goto         stop         ;If stop button, go to stop 



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.



; at blast time, select:

;     memory uprotected

;     watchdog timer disabled

;     standard crystal (4 MHz)

;     power-up timer on


 Time control

Example 3: timer1_0 - blink an LED at a desired rate

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:

Note: download timer1_0.asm rather than cutting and pasting from below. The resulting HEX file timer1_0.hex can be burned into the PIC16F84.  

; FILE: timer1_0.asm - WORKS!

; AUTH: P.Oh

; DATE: 1.0 - 04/14/02 16:00

; DESC: 1.0 - Internal timer, blink LED every 32.8 msec

; NOTE: Tested on PIC16F84-04/P. 

;       Page numbers in code are in Easy Pic'n book.

;       4 MHz crystal yields 1 MHz internal clock frequency.

;       "option" is set to divide internal clock by 256.

;       This results in 1 MHz/256 = 3906.25 Hz or 256 usec.

;       tmr0 bit 7 (128 decimal) is checked, thus yielding

;       128*256 usec = 32.8 msec delay loop

; REFs: Easy Pic'n p. 113

                list    p=16F84

                radix   hex 


;       cpu equates (memory map)

portB   equ     0x06           ; (p. 10 defines port address)

count   equ     0x0c

tmr0    equ     0x01


            org     0x000

start      clrwdt                 ; clear watchdog timer

            movlw b'11010111'    ; assign prescaler, internal clock and divide by 256 see p. 106


            movlw   0x00           ; set w = 0

            tris       portB          ; port B is output

            clrf      portB          ; port B all low

go        bsf        portB, 0       ; RB0 = 1, thus LED on p. 28

            call       delay

            bcf       portB, 0       ; RB0 = 0, thus LED off

            call       delay

            goto    go             ; repeat forever 

delay   clrf       tmr0           ; clear TMR0, start counting

again   btfss     tmr0, 7        ; if bit 7 = 1

            goto    again          ; no, then check again

            return                 ; else exit delay 



; at blast time, select:

;       memory uprotected

;       watchdog timer disabled

;       standard crystal (4 MHz)

;       power-up timer on


 To have a 0.5 second delay, we will need to put this in a loop that will need to execute approximately 15 times.

Cnt       equ       0x0b


            movlw  0x0e

            movwf  cnt

delay    clrf       tmr0           ; clear TMR0, start counting again

            btfss     tmr0, 7        ; if bit 7 = 1               

            decfsz  cnt,f           ;Decrement counter until it reach zero.

            goto     delay                ;

            return                           ;

Comparing data

This section shows you how to compare data in your program. For example, let say you want to check if your input data from porta a arrange in binary base is equal to hex base 5. You would first read move data from porta to Working Register. Then subtract this from hex number 5. Then we will check the zero flag in the Status Register to see if it is set or not. If it is set, this mean that result from the calculation is zero. Therefore out number is hex 5.


movf     porta,w                        ;load porta to Working register and then

sublw   0x05                            ; subtract 5 from it. Result in W

btfss     Status,2                        ;check if zero flag is set

goto     code here                     ; If not

goto                 code here                     ; if Yes..

Here is a useful table of to check for flag in the Status Register.

For this code:

sublw   N         ;subtract N from W     

Test For

Flag Tested

W = N

Z Set

W /= N

(not Equal)

Z Clear

W <=  N

C Set

Practice Good Programming Style:

Be sure to use appropriate comments to describe your code.


Molw      b’00000001’ ;Turn on line zero of portb
Movwf    portb

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.

Final Words

You should be able to start coding for the Pic as of now. These basic skills will be the building block for your future works. Don’t under-estimate the power of a small chip. With the right program, build a well plan circuit, burn the program to the chip; you can put this chip to work with the computation power greater than any human being. :o) Hope you enjoy the exercise. And hope that you learn something from it.

If you have any question regards my tutorial.

Click here to email me


In print

o    Easy PIC'n by David Benson at first glance appears to be a tersely written book. After you build and program your first PIC16F84 circuit, you begin to appreciate the book's concise style and excellently explained assembly code. Easy PIC'n as well as PIC'n Techniques is published by Square 1.

o      Pic your Personal Introductory Course 2nd, John Morton

o          Pic’n up the pace by David Benson, Publish by Square1

o          Microcontol’n Apps, by David Benson. Publish by Square 1

o          Pic Basic Programming and Progjects, Dogam Ibrahim, Publish by Biddles Ltd


o  Boondog

o  A PIC16F84-based ultrasonic sensor.

o  Cooper Tools

o  Picall Programmer

o  Jameco Electronic