Site hosted by Build your free website today!

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:

o       Parts List and Sources

o       Introduction to 16F84 Microprocessor

o       Building the Circuit

o       Programming Preparation

o       Induction to microprocessor programming

o       Some programming example

o       Final Words


Part 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
















































To Top of Page



 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


PIC16F84-04/P IC
CMOS PIC Microcontroller  

·         Pins: 18

·         Configuration: Flash

·         Speed: 4MHz

·         EPROM bits: 1K x 14

·         RAM bytes: 68

·         I/O lines: 13




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

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




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. A quater was there to show the actual size of the board.





Purposes of the parts?

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.
  • Pins: 40



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.


Picture of the board with a  4.8 V battery attached


This is the back of the board showing the wiring.


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.


 To Top of Page




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


 To Top of Page





Program the PIC as easy as ABC

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.


;           Description                          *

;                                                   *



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   porta ;teach portb to be an input

movlw  0x00  ;load w(working register)with 0x00

tris   portb  ;teach portb to be an output


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


Code’s 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

(invert all data in temp and save back into temp)

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

Loop  BTFSC    porta,2

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 if Set

Loop  BTFSS    porta,3

Goto           loop

(this loop is on as long as line 3 of porta is a 0)

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



      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

W > N

C Clear



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               


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





 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



 To Top of Page