• Learning how PICs work and how to apply them involves study in three
areas:
• IBM compatible computer use (as needed).
• Assembler
• PIC itself.
CLOCK OSCILLATOR
• Four different types of clock oscillators may be used with PICI6F84 parts
in general. The clock oscillator types are:
• RC -resistor/capacitor.
• XT -crystal or ceramic resonator -external clock.
• HS -high speed crystal or ceramic resonator -external clock.
• LP -low power crystal –external clock.
• At programming time, the PIC must be told via configuration bits what
type of oscillator it will be connected to.
• The details of various oscillator circuits and components are given in the
Microchip data book available online.
• One possible clock circuit for experimentation is a 4 MHz crystal-
controlled oscillator (type XT). They are accurate, always start and the
math required for designing time delay loops is simple.
• The external clock frequency is divided by 4 internally, so the internal
clock frequency is 1MHz.
• Almost all instructions are executed in one instruction (internal clock)
cycle or 1microsecond in this case. This is reasonably fast for
experimenting purposes.
• An RC clock circuit may also be used where cost is an issue and timing
accuracy is not. The oscillator type code is RC.
CONFIGURATIONBITS
The configuration bits are located in Flash memory outside the main part of
Flash memory used for program storage. There are five configuration bits.
Two select clock oscillator type, one is the watchdog timer enable bit, one is
the power-up timer enable bit and one is the code protection bit. The device
programmer accesses these bits during the device programming procedure.
• The PICl6F84 has built-in power-on reset which works as long as the
power supply voltage comes up quickly. Commonly the MCLR pin is
merely tied to the power supply. A switch may be used to regain control
if things run away.
PORTS
• The Port B lines have weak pullup resistors on them which may be
enabled or disabled under software control.
• All 8 resistors are enabled/disabled as a group via the RBPU bit in the
option register. The pullup resistor on an individual port line is
SPECIAL FEATURES
Watchdog Timer
The watchdog timer is useful in some control applications where a runaway
program could cause a safety problem. We will not deal with it except to say
that it is important to select "watchdog timer off' when programming the
configuration bits.
Power-up Timer
The power-up timer should be selected "ON" when programming the
configuration bits.
Sleep Mode
The feature of the "sleep mode" is to drastically reduced power consumption
achieved by turning off the main clock oscillator.
The block diagram for the PIC16F84 microcontroller is shown in Figure 2.0.
• Program memory
• Data memory.
Each memory-block has its own bus to allow simultaneous accessing during
the same oscillator cycle. This is the Harvard architecture, which improves
bandwidth over traditional von Neumann architecture.
The special function registers (SFRs) are used by the CPU and peripheral
functions to control the device operation (these registers are SRAM) and
occupy the first 12 file addresses corresponding to 80h (128) up to 8Bh
(139), i.e. (128, 129, .., 138, 139).
The general purpose registers (GPRs) commence from 8Ch (140) up till
CFh (207), so that there are a total of (207 – 140 + 1) = 68.
The unimplemented data memory locations commence from D0h (208) up
till FFh (255), so that there are a total of (255 – 208 + 1) = 48.
There are two banks: banks 0 and 1. For bank 0, the 12 SFRs are from 00h
(0) to 0Bh (11) or 11 – 0 + 1 = 12 addresses. The 68 GPRs are from 0Ch
EE313 Microprocessor Applications 11 R Singh
(12) to 4Fh (79) or (79 – 12 + 1) = 68, the unimplemented are from 50h (80)
to 7Fh (127) or (127 – 80 + 1) = 48.
Since an instruction is executed every four clock cycles, the PIC16F84 can
do calculations, read input values, store and retrieve information from
memory, and perform other functions very quickly. With a clock speed of 4
MHz an instruction is executed every microsecond and 1 million instructions
can be executed every second.
The RAM, in addition to providing space for storing data, maintains a set of
special purpose byte-wide locations called file registers. The bits in these
registers are used to control the function and indicate the status of the
microcontroller.
3.4 PORTS
The PIC16F84 is packaged on an 18-pin DIP IC that has the pin schematic
(pinout) shown in Figure 3.4.
Table 3.4 lists the pin identifiers in natural groupings, along with their
descriptions. The five pins RA0 through RA4 are digital I/O pins
collectively referred to as PORTA, and the eight pins RB0 through RB7 are
digital I/O pins collectively referred to as PORTB. In total, there are 13 I/O
lines, called bidirectional lines because each can be individually configured
in software as an input or output. PORTA and PORTB are special purpose
file registers on the PIC that provide the interface to the I/O pins. Although
all PIC registers contain 8 bits, only the 5 least significant bits (LSBs) of
PORTA are used.
TABLE 3.4
3.5 Interrupt
In the PIC16F84, pins RB0 and RB4 through RB7 can be configured as
interrupt inputs.
Power and ground are connected to the PIC through pins Vdd and Vss. The
dd and ss subscripts refer to the drain and source notation used for MOS
transistors, since a PIC is a CMOS device. The voltage levels (e.g., Vdd =
5V and Vss = 0 V) can be provided using a DC power supply or batteries
(e.g., four AA batteries in series or a 9-V battery connected through a
voltage regulator).
The master clear pin ( MCLR ) is active low and provides a reset feature.
Grounding this pin causes the PIC to reset and restart the program stored in
EEPROM. This pin must be held high during normal program execution.
hence connected with a pull-up resistor.
To provide a manual reset feature to a PIC design, you can add a normally
open (NO) pushbutton switch as shown in Figure 3.5. Closing the switch
grounds the pin and causes the PIC to reset.
Instruction Set
The assembly language used to program a PIC16F84 consists of 35
commands that control all functions of the PIC. This set of commands is
called the instruction set for the microcontroller.
The complete instruction set and brief command descriptions for the
PIC16F84 are listed in Table 4.0.
TABLE 4.0
For example, BCF PORTB, 1 makes bit 1 in PORTB go low (where PORTB
is a constant containing the address of the PORTB file register). If PORTB
contained the hexadecimal (hex) value FF (binary 11111111) originally, the
final value would be hex FC (binary 11111101). If PORTB contained the
hex value A8 (binary 10101000) originally, the value would remain
unchanged.
For example, MOVLW 0xA8 would store the hex value A8 in the W register.
In assembly language, hexadecimal constants are identified with the 0x
prefix.
For example, if the memory location at address hex 10 contains the value
hex AB, then SWAPF 0x10, 0 would store the value hex BA in the W
register. SWAPF 0x10, 1 would change the value at address hex 10 from hex
AB to hex BA.
You are required to write an assembly program such that PORTA and
PORTB of the PIC16F84 IC become output ports. Then output data 01H and
0FH at PORTA and PORTB respectively. Continue this operation in an
infinite loop.
START
(HEADER)
list p=16F84
radix hex
Clear PORTA
Clear PORTB
END
list p=16f84
radix hex
;-----------------------------------------------------------------------
; (EQUATES)
;
porta equ 0x05 ;equate "porta" to point to file register (SPR) 0x05
portb equ 0x06 ;equate "portb" to point to file register (SPR) 0x06
;------------------------------------------------------------------------
;(ORIGIN)
;
goto go ;repeat
;----------------------------------------------------------------------------------------
;(END OF MAIN PROGRAM)
;
end
;----------------------------------------------------------------------------------------
You are required to write an assembly program such that PORTA and
PORTB of the PIC16F84 IC become output ports. Then output data 05H and
E0H at PORTA and PORTB respectively. Continue this operation in an
infinite loop.
START
(HEADER)
list p=16F84
radix hex
Clear PORTA
Clear PORTB
END
porta equ 0x05 ;equate porta to point to file register (SPR) 0x05
portb equ 0x06 ;equate portb to point to file register (SPR) 0x06
;----------------------------------------------------------------------------------------
;(ORIGIN)
;
org 0x000 ;program originates at location 0x00
;----------------------------------------------------------------------------------------
----------
; (MAIN PROGRAM)
;
start movlw 0x00 ;load W register with 0x00
tris porta ;copy W to tristate PRORTA --> PORTA set as output
go
bsf porta,0 ;set bit 0 of porta file register
bsf porta,2 ;set bit 2 of porta file register
bsf portb,5 ;set bit 5 of portb file register
bsf portb,6 ;set bit 6 of portb file register
bsf portb,7 ;set bit 7 of portb file register
goto go ;repeat
;----------------------------------------------------------------------------------------
;(END OF MAIN PROGRAM)
;
end
;----------------------------------------------------------------------------------------
You are required to write an assembly program such that PORTA (RA0)
becomes an input and PORTB (RB0) an output port respectively. Next,
connect a SWITCH (Switch 5) to RA0 and a LED (Led1) to RB0. Write an
assembly program so that the LED turns on each time the switch is pressed.
START
(HEADER)
list p=16F84
radix hex
Clear PORTA
Clear PORTB
Is
SWITCH
Pressed ? N
Turn ON LED
END
porta equ 0x05 ;equate porta to point to file register (SPR) 0x05
portb equ 0x06 ;equate portb to point to file register (SPR) 0x06
;----------------------------------------------------------------------------------------
;(ORIGIN)
;
org 0x000 ;program originates at location 0x00
;----------------------------------------------------------------------------------------
; (MAIN PROGRAM)
;
movlw 0x01 ;load W register with 0x01
tris porta ;copy W to tristate PRORTA --> PORTA RA0 set as input
begin btfss porta,0 ; if switch5 at RBO pressed skip next line else test for
;switch pressed.
goto begin ;goto begin
;-------------------------------------------------------------------------
;(END OF MAIN PROGRAM)
;
end
;-------------------------------------------------------------------------
You are required to write an assembly program such that PORTA (RA0)
becomes an input and PORTB (RB0) an output port respectively. Next,
connect a SWITCH (Switch 5) to RA0 and a LED (Led1) to RB0. Write an
assembly program so that the LED flickers (on/off) each time the switch is
pressed.
(HEADER)
list p=16F84
radix hex
Clear PORTA
Clear PORTB
Is
SWITCH
Pressed ? N
Y
Turn ON LED
DELAY
DELAY
END
porta equ 0x05 ;equate porta to point to file register (SPR) 0x05
portb equ 0x06 ;equate portb to point to file register (SPR) 0x06
count1 equ 0x0C
count2 equ 0x0D
;------------------------------------------------------------------------
;(ORIGIN)
;
org 0x000 ;program originates at location 0x00
;-------------------------------------------------------------------------------------
; (MAIN PROGRAM)
;
movlw 0x01 ;load W register with 0x01
tris porta ;copy W to tristate PRORTA --> PORTA RA0 set as input
begin btfss porta,0 ; if switch5 at RBO pressed skip next line else test for
;switch pressed.
goto begin ; goto begin
;-------------------------------------------------------------------------
;(SUBROUTINE PROGRAM)
delay movlw 0xFF ;load Decimal FF in W register
movwf count1 ;load Count1 with contents of W register
loadC2 movlw 0xFF ;load Decimal FF in W register
movwf count2 ;load Count2 with contents of W register
decC2 decfsz count2,f;decrement counter2 and skip next line if Z=0
goto decC2 ; if count2 not 0 than go to decC2
decfsz count1,f;decrement counter1 and skip next line if Z=0
goto loadC2 ; if count1 not 0 than go to loadC2
return ;else jump out of subroutine
;-------------------------------------------------------------------------
;(END OF MAIN PROGRAM)
;
end
;-------------------------------------------------------------------------
Using all the experience gained from the four programming exercises
covered in class, you are required to complete a small project.
First connect a push button switch SW1 to PORTB (RB0) and two LEDs
to PORTA i.e. LED1 to RA0 and LED2 to RA1 as shown in Figure 1.0.
When a switch is pressed the jagged signal would last for less than 20ms.
So incorporating a 20ms delay subroutine after reading a switch input
and repeating to read the switch input would solve the debounce problem.
START
(HEADER)
list p=16F84
radix hex
Clear PORTA
Clear PORTB
Is
SWITCH
Pressed ? N
Turn ON LED
END
If you don’t want to use the software approach, you can use a capacitor to
filter the bouncing signal and pass it into a Schmitt trigger input. Schmitt
trigger inputs have different thresholds, depending on whether the signal is
rising or falling. For rising edges, the trigger point is higher than falling.
Schmidt trigger inputs have the “hysteresis” symbol put in the buffer as
shown in Figure 7.2.
;(SUBROUTINE PROGRAM)
;-------------------Delay Subroutine-----------------------------------------------------
Delay movlw 0xFF ;load Decimal FF in W register
movwf count1 ;load Count1 with contents of W register
loadC2 movlw 0xFF ;load Decimal FF in W register
movwf count2 ;load Count2 with contents of W register
decC2 decfsz count2,f;decrement counter2 and skip next line if Z=0
goto decC2 ; if count2 not 0 than go to decC2
decfsz count1,f;decrement counter1 and skip next line if Z=0
goto loadC2 ; if count1 not 0 than go to loadC2
return ;else jump out of subroutine
START
COUNT3 = 5
Turn ON LED1
DELAY SUBROUTINE
Decrement COUNT3
Is
COUNT3=0 ?
N
Turn ON LED2
DELAY SUBROUTINE
END
;----------------------------------------------------------------------------------------------
;(ORIGIN)
;
org 0x000 ;program originates at location 0x00
;----------------------------------------------------------------------------------------------
; (MAIN PROGRAM)
;
movlw 0xFC ;load W register with 0xFC
tris porta ;copy W to tristate PRORTA --> PORTA RA0 & RA1 set as input
start clrf porta ;clear all lines of porta to low (LED1 & LED2 OFF)
• The Data Memory is partitioned into multiple banks which contain the
Special Function Registers and General Purpose Registers
• Each Bank extends up to 7FH (128 bytes). Bits RP1 (STATUS<6>)
and RP0 (STATUS<5>) are the bank select bits.
CORE FEATURES
• More I/O pins (PortA, PortB, PortC, PortD & PortE)
• 8K Program Memory
• Can be operated with 20MHz clock input (200ns instruction
cycle)
PERIPHERAL FEATURES
• 10-bit multi-channel Analog-to-Digital converter
• Two Capture, Compare, PWM modules
• 3 Built in TIMER (Timer0, Timer1 & Timer2)
• Interrupt capability (up to 14 sources)
• Eight level deep hardware stack
• Synchronous Serial Port (SSP) with SPITM (Master mode) and
I2CTM (Master/Slave)
• Universal Synchronous Asynchronous Receiver Transmitter
(USART/SCI) with 9-bit address detection
• Parallel Slave Port (PSP) 8-bits wide, with external RD , WR
and CS controls (40/44-pin only)
The best part is that PIC16F877 Bootloader boards are very reliable.
‘ Use the white box on the toolbar to select the compiler. CCS offers different
compilers for each family of Microchip parts. All the exercise in this course are for
the PIC16F877 chip, a 14-bit opcode part. Make sure 14 bit is selected in the
white box.
‘ The main program compiled is always shown in the lower right corner of the
IDE.
‘ Click File > New and create file name Exercise1.C as shown
‘ The “while (TRUE)” is a simple way to create a loop that never stops.
‘ Note the “output_A(0xFF)” outputs logic high (5V) to all the pins of PORTA
and “output_A(0x00)” outputs logic low (0V) to all the pins of PORTA.
‘ Click Compile > Compile and the following files should be created as shown
‘ Reset the bootloader and the program starts running. Connect the output pins of
all the ports to a LED and verify that they cause the LED to flick On and OFF at
1sec interval.
Note: This simple program can always be used to test if all the pins of the
microcontroller are working or not.
‘ Once this program is complied, downloaded to the bootloader and run only
PIN_A0 output flicks ON and OFF.
‘ The function “wait_for_one_press()” will first get stuck in a loop while the input
pin is low (not pressed). When ever a button is pressed once, is it common for
several very quick connect/disconnect cycles to occur. The100ms delay takes
care of this switch debounce. It then waits in another loop while the pin is high.
The function returns as soon as the pin goes low again. Note that the loops,
since they do not do anything while waiting, do not look like much– they are a
simple ; (do nothing).
‘ Click File > New and create file name Exercise4.C as shown.
‘ For this exercise a 5V variable input supply would be required which should be
connected to PORTA pin0 (RA0). A variable power supply can be used but if you
have a power supply with fixed voltage output then design a voltage divider
circuit as shown. Note: INPUT SHOULD NOT EXCEED 5V.
to common
PIC ground
‘ The call to “read_adc()” starts a conversion, waits for it to complete and returns
the result. The conversion time is around 20 us.
‘ Once this program is complied, downloaded to the bootloader and run, the 0 to
5volts variable voltage would be read in at PORTA pin0 (RA0) and the
corresponding voltage displayed on the Tera Term window every 1 second.
12.70 V
A: rl_2
7.700 V
2.700 V
-2.300 V
-7.300 V
-12.30 V
0.000us 50.00us 100.0us 150.0us 200.0us 250.0us 300.0us 350.0us 400.0us 450.0us 500.0us
FIGURE 4.0
SOLUTION
(i) Since the peak voltage Vpeak = 11.5V we need a voltage divider circuit as
shown in Figure 4.1 to reduce this voltage to 5V which can be read in by the PIC
microcontroller.
FIGURE 4.1
(ii) In the program the following line should change to display the correct voltage
volt = value * (float)5/255;
to
volt = value * (float)11.5/255;
ROW1
ROW2
FIGURE 5.0
ROW3
ROW4
COL1
COL2
COL3
FIGURE 5.1
‘ Connect up the row and column outputs of the matrix keypad to the appropriate
pins of the PIC 16F877 microcontroller as outlined in the table below
‘ Once this program is complied, downloaded to the bootloader and run, random
key presses should be detected and displayed on the Tera Term window. To
correct this error 10k ohms “Pull Down resistors” should be connected from
each of the four Row outputs to ground as shown in Figure 5.2.
EXERCISE:
(i) Carefully study the Keypad.C program and use it to draw a flow chart of the
program.
(ii) Modify the Keypad.C program to read in all the key inputs from the 4X4
keypad. A valid key press is one where the input key switch first “closes” and
then “opens”. Save this modified Keypad.C program for future use.
‘ For a LCD display with 80 characters or less (all but the 40x4 just listed), the
display is controlled via 14 pins. The names and descriptions of these pins are
listed in Table 6.0. LCD displays with more than 80 characters (40x4) use a 16-
pin header with different pin assignments. A 14-pin LCD can be controlled via
‘ Commands and data are sent to the display via lines DB4 through DB7, and
lines DB0 through DB3 (pins 7 through 10) are not used.
‘ The potentiometer connected to Vee is used to adjust the contrast between the
foreground and background shades of the display. The RS, R/W, and E lines are
controlled automatically by PIC C program when communicating with the display.
FIGURE 6.0
TABLE 6.0
Problem only arises when there are not enough I/O pins for the number of I/O
devices to be interfaced. This situation can be overcome by using Decoders as
shown in the figure below:
‘ Click File > New and create file name Interrupt1.C as shown on page 61
ENABLE_INTERRUPTS()
Returns: undefined
Function: Enables the interrupt at the given level. An interrupt procedure should have
been defined for the indicated interrupt. The GLOBAL level will not enable any
of the specific interrupts but will allow any of the specific interrupts previously
enabled to become active.
Requires Should have a #int_xxxx, Constants are defined in the devices .h file.
Examples: enable_interrupts(GLOBAL);
enable_interrupts(INT_RB);
enable_interrupts(INT_EXT);
_____________________________________________________________
#INT_xxxx
Purpose: These directives specify the following function is an interrupt function. Interrupt
functions may not have any parameters. Not all directives may be used with all
parts. See the devices .h file for all valid interrupts.
The compiler will generate code to jump to the function when the interrupt is
detected. It will generate code to save and restore the machine state, and will
clear the interrupt flag. To prevent the flag from being cleared add NOCLEAR
after the #INT_xxxx. The application program must call
ENABLE_INTERRUPTS(INT_xxxx) to initially activate the interrupt along
with the ENABLE_INTERRUPTS(GLOBAL) to enable interrupts.