Académique Documents
Professionnel Documents
Culture Documents
5th Edition
Sept 2002
The MicroBoard: Design and Assembly - This part introduces the features of the MicroBoard
and gives some background information on its design. A MicroBoard assembly guide is included
here.
II.
Getting Started: Programming the PIC - The second part provides you with a brief review of
assembly language programming and the PIC instruction set. Here you will find a template that
you can use as a starting point for writing your own assembly language program. This part
concludes with instructions on assembling your assembly language program and downloading
object code to the PIC microcontroller.
III.
The MicroBoard In Action - This part contains the information you need to make your
MicroBoard actually do something. It begins by introducing the operation of the MicroBoard in
Hosted mode and will outline some of the methods you can use to test drive your board. It then
steps through the features of the PIC microcontroller, one-by-one, complete with instructions,
diagrams, sample code and working examples. Equipped with the information provided here, you
will be able to unleash the full capabilities of the MicroBoard.
IV.
Appendices - These are referenced by the three previous parts. Feel free to detach the appendices
from the bulk of this manual; you will likely refer to them often.
This manual is intended to be a supplement to the PIC16F87X data sheet, which can be downloaded from
the EE401 website (www.ee.ualberta.ca/~ee401). The PIC16F87X data sheet includes absolutely
everything you will need to know about the PIC16F87X microcontroller and this user manual refers to it
often. Another helpful reference is the PICmicro Midrange Reference Manual, which can also be found on
the EE401 website. I would sincerely recommend taking the time to read this entire manual from
beginning to end and to familiarize yourself with the data sheet; the things you will learn along the way will
be helpful when it comes to designing your own project. Be aware, however, that completion of this
manual will merely lay the groundwork for more interesting, albeit more useful, applications of the
MicroBoard.
Keep in mind that the MicroBoard is just the central nervous system of your project. You are responsible
for the design of the extraneous circuits that your project will utilize (sensors, motors, etc). It would be
prudent to make your initial circuit designs on an SK10 board, then later transfer your design to a computer
using EAGLE to have it milled into a clean PCB. In general, rats nests of wires dont hold up very well
and, in accordance with Murphys Law, will inevitably let you down when you need them the most (during
demonstrations of course!).
Contributors
This document was created by contributions from: Dave Bull, Ben Bathgate, Mike Cumming, Patrick
Pilarski, Paul Bartosek and Loren Wyard-Scott.
Table of Contents
Part I The MicroBoard: Design and Assembly
1.0 Introduction to the MicroBoard
1.1 MicroBoard Specifications
1.2 Functional Description
1.2.1 DC Power Supplies
1.2.2 RS-232 Serial Interface
2.0 MicroBoard Assembly
Part II Getting Started: Programming the PIC
3.0 Programming the PIC Microcontroller
3.1 Assembly Language Programming
3.2 Memory Structure
3.3 Instruction Set
3.3.1 Mathematical Operations
3.3.2 Flow Control
3.4 Subroutines
3.5 Interrupts
3.6 Putting It All Together
4.0 Assembling Your PIC Program
4.1 Writing Your Program to the PIC
Part III The MicroBoard In Action
5.0 Debug87x
5.1 Hardware Flow Control
6.0 Peripheral Features
6.1 I/O Ports
6.1.1 Port A (and Port E)
6.1.2 Port B
6.1.3 Port C
6.1.4 Port D
6.1.5 Using Digital I/O Ports Example
6.1.6 Using I/O with Debug87x.hex
6.2 Parallel Slave Port (PSP) Module PIC16F877 only
6.2.1 Using the Parallel Slave Port Example
6.3 Timer Modules
6.4 Master Synchronous Serial Port (MSSP)
6.4.1 Serial Peripheral Interface (SPI)
6.4.2 Adding Additional Outputs Using Shift Registers and SPI
6.4.3 Using SPI with Debug87x.hex
6.4.4 Using the LCD with Debug87x.hex
6.4.5 Writing a C Program To Control The LCD
6.5 Universal Synchronous Asynchronous Receiver Transmitter (USART)
6.5.1 Using the USART with a Personal Computer
6.5.2 Writing a C Program To Send Text To A Terminal Window
6.6 Pulse Width Modulator (PWM)
6.6.1 Using the Pulse Width Modulator with Debug87x.hex
Part I
The MicroBoard:
Design and Assembly
PIC16F873
PIC16F877
28
40
6-18 Vdc
5 Vdc
Clock Speed
22
33
5 (multiplexed)
8 (multiplexed)
No
Yes
No
Yes
No
Yes
20 mA @ 7.2 Vdc
500 mA
500 mA
50 mA
* See the course instructor for details in regards to upgrading the clock speed.
DC power is supplied to the board through a 2.1mm coaxial barrel connector with center positive polarity.
Normally this power comes from a 9Vdc 500mA wall adaptor plugged into the barrel connector. However,
a 12Vdc 1A wall adaptor or suitably sized battery array can also be used. In the lab you will find
connectors that allow you to connect your MicroBoard to a DC power supply.
Diodes D1 and D2 provide some reverse polarity protection and power supply transient isolation.
Capacitors C1 and C2 provide power supply bulk charge storage while C3-C6 provide additional power
supply transient isolation for their respective supplies.
IC1 (7805) regulates the bulk supply to the +5Vdc needed for the PIC micro-controller and logic devices
(logic side of the L293 and MAX232). IC2 (7812) and its components regulate the bulk supply for the
voltage inverter, IC3, and are only installed if IC3 is to be used. IC3, the ICL7662P, and capacitors C9C14 provide a negative voltage for analog circuits such as dual supply op-amp circuits.
You will notice that the polarized capacitors have a non-polarized capacitor in parallel with them. This is
not always necessary in designs but is here. The reasoning is that real capacitors are not ideal capacitors:
larger capacitors tend to have greater amounts of intrinsic inductance associated with them due to their
construction. Their greater inductance gives them poorer high frequency performance. Smaller capacitors
tend to have better high frequency performance. Therefore, multiple real capacitors are used to
approximate the required ideal capacitor performance.
The RS-232 circuitry consists of a DB9 female connector, the MAX232 and related circuitry. The DB9
connector is configured for an IBM PC-style 9-pin RS-232 connection. The MAX232 converts the RS-232
(sometimes called the HIN232) +/-12V signals to logic levels for the micro-controller. The resistors R31
and R32 (330) limit line slew rates and provide some short circuit protection. The resistors R23, R24 (not
shown here, see Appendix A Microboard Schematic Diagrams), R33 and R34 provide output contention
protection (contention is created if the Digital I/O pin of PIC incorrectly configured as an output and is
connected to the output of the MAX232). C24C25 are used by the on-board charge-pump (note that the
supply is +5V and yet the IC can deliver RS-232 level signals).
Soldering Iron.
63/37 electronic grade rosin core solder.
Flux pen.
Needle nose pliers for forming leads.
Side cutters for cutting leads.
If you are not familiar with soldering and circuit board assembly you may want to read Appendix C
Soldering Tips before continuing. If you have questions about MicroBoard assembly dont hesitate to ask
your TA. Thats what they are there for. You can waste a lot of time and effort simply finding and
repairing a bad solder joint. Do it right the first time and your life will be more pleasant.
Remember these axioms whenever working with electronics.
Keep it clean.
It is easier to keep electronics clean than to clean electronics. Contamination may cause
problems: a simple fingerprint will etch a copper trace and foul a solder connection; a
fingerprint or leftover flux residue can act as an undesirable resistor.
Keep it cool.
Use the correct soldering techniques and temperature. High temperatures will destroy
components or shorten life times.
Minimize stress.
Miniaturization means less mechanically robust component packaging. Allow for thermal
expansion, mechanical flexing, and component movement. Do not pull leaded components
too tightly to the board.
The MicroBoard schematics and board layout diagrams are included in the assembly packages. Use these
to locate the placement of the components on the MicroBoard. In your assembly package you will also find
an assembly checklist. It is recommended that you solder the components in that order, checking them off
as you go.
WARNING! Do not solder ICs directly into the board!
Solder the IC sockets.
When the assembly of your MicroBoard is complete you should test the power supply circuitry before
installing any ICs. Your assembly package includes a power checklist that guides you through this process.
Now that your MicroBoard is assembled and working properly you can do one of two things:
1.
2.
Part II
Getting Started:
Programming The PIC
Program memory
Data memory
EEPROM data memory
1.
Program Memory
The program memory is, as you may have guessed, the section where your program instructions
are stored. The size of the program memory for the PIC16F873 is 4Kx14 which means that it can
hold 4x1024=4096 14-bit instructions. The program memory for the PIC16F877 is 8Kx14.
The program memory is divided into 2K blocks called pages. Thus, the PIC16F873 has 2 pages of
program memory and the PIC16F877 has 4 pages. In order for commands on a certain program
memory page to be executed the corresponding page must be selected. To switch between
program memory pages use the pagesel directive.
A recommended way to use the pagesel directive is to first define the following values at the
beginning of your assembly language program as follows (also see section 3.6):
page0
page1
page2
page3
EQU
EQU
EQU
EQU
0x0000
0x0800
0x1000
0x1800
;
;
;
;
start
start
start
start
address
address
address
address
of
of
of
of
page0
page1
page2
page3
Then to select a page, say page 2 for example, use the following in the body of your main
program:
pagesel
2.
page2
Data Memory
The data memory is divided up into 4 banks (bank 0-bank 3) that contain both Special Function
Registers and General Function Registers. See Figures 2-3 and 2-4 in the PIC16F87X data sheet
for register file maps. The special function registers are named and have a predefined function.
They are used for controlling the operation of the microcontroller. Some of the more important
Special Function Registers are outlined in section 2.2.2 of the PIC16F87X data sheet. General
function registers are used for data storage. The PIC16F873 has 192 8-bit general function
registers. The PIC16F877 has an additional 176 8-bit general function registers (368 in total).
To access a register in a certain data memory bank you must ensure that the appropriate bank is
selected. The status of the bank select bits, RP0 and RP1 (located in the STATUS register),
determine which data memory bank is active. See section 2.2 in the PIC16F87X data sheet for a
table of bank select bits. For example, to access the general purpose register at address 0xA0 you
must select bank 1 (i.e. RP1:RP0 =01).
The banksel directive can also be used to select the desired data memory bank, similar to the way
in which the pagesel command is used to select the desired program memory page. First define
the following values:
BANK0
BANK1
BANK2
BANK3
EQU
EQU
EQU
EQU
0x0000
0x0080
0x0100
0x0180
Then to select the bank, say bank1 for example, use the following in the body of your main
program:
banksel
3.
BANK1
EEPROM Memory
The EEPROM memory is nonvolatile meaning its contents are not erased when you turn off the
power to the PIC. This is useful for storing information such as the state of your system before it
is powered-down since this information can then be retrieved when the system is powered-up
again. Data stored in the Data memory section (RAM) is erased when the power is removed from
the PIC. For instructions on using EEPROM see section 4.0 in the PIC16F87X data sheet.
STATUS , RP0
STATUS , RP1
Remember that the RP0 and RP1 bits are used to select the data memory bank. The instructions above will
select bank 1 (i.e. RB0:RB1=01).
The following is an example of a byte-oriented instruction.
clrf
STATUS
Many instructions use the W register, which you can think of as a temporary storage place. To store a
value in one of the general purpose registers, say at address 0x20 (in bank 0), you could use the following
commands:
bcf
STATUS , RP0
bcf
STATUS , RP1
movlw
0x35
movwf
0x20
; select bank 0
; writes 0x35 to the W register
; moves the value from the W register to the
; general purpose register at address 0x20
To make your code more readable you can define labels to replace numerical values. These labels are
defined at the beginning of your program using the EQU (equate) assembler directive.
length
lreg
EQU
EQU
0x35
0x20
With these defined the above instructions could now be replaced with:
movlw
length
movwf
lreg
An additional benefit to using labels is that if you decide to change any one of the values in your source
code, you need to only change the value of the label rather than having to search through your entire source
code for every occurrence of that value.
lreg , W
Here the W register is the destination for the result of the addition, as specified by the second argument to
the instruction. Alternatively, you can specify lreg to be the destination register by replacing W with F
(file).
addwf
lreg , F
STATUS , RP0
STATUS , RP1
; Select bank 0.
decfsz
lreg , F
goto
goto
:
:
LOOP
ZERO
;
;
;
;
;
LOOP
Decrement the value in the lreg
register and skips the next
instruction if the result is 0.
Branch to LOOP if result not 0.
branch to ZERO if result is 0.
ZERO
{instructions}
:
3.4 Subroutines
Using subroutines is a way to make your program modular. It also shortens the length of your main
program making it easier to follow.
You can think of subroutines as mini programs that are called from the main program. Subroutines are
usually defined after the main program. Consider the code below:
main
{main program instructions}
:
call incW
; call incW subroutine
:
goto
main
W
W
W
return
Here a subroutine called incW is defined. The purpose of the subroutine is to increment the value in the W
register 3 times. In the main program you call the subroutine using the call instruction with the subroutine
name as the operand. When the call command is executed the main program jumps to the incW subroutine,
executes the commands defined there, then returns to the main program when the return instruction is
executed.
Unlike many other microcontrollers, the PIC contains no user-accessible stack. Adding the fact that the
programmers model contains only one working register, subroutines passing more than a single byte need
to make use of the file register memory. Additionally, the stack in the PIC16F87X devices is only 8
locations deep. Recursive calling is thereby discouraged. Interrupts, described next, also require stack
locations and reduce the possible call-depth.
3.5 Interrupts
Interrupts are an alternative to polling for events and can make processing time more efficient, since your
program doesnt need to wait for selected events to occur by polling. Every time a selected event triggers
an interrupt, the PIC stops execution of the program and jumps to the interrupt service routine. Once
finished, the PIC resumes normal execution of your program, where it left off.
Each of the built-in modules has the ability to cause an interrupt for one reason or another. The ADC, for
example, can cause an interrupt when it has completed a conversion while the UART can produce an
interrupt when its transmit buffer is empty or when its receive buffer is full.
When an interrupt occurs, the PIC jumps to the program memory location 0x0004, the interrupt vector. The
program space available in this location is very limited so its recommended that you place your interrupt
service routine (ISR) elsewhere in program memory and just put a GOTO command in the interrupt vector
space (see the example program in section 3.6). Instructions on writing Interrupt Service Routines (ISRs)
are provided in section 12.10 of the PIC16F87X data sheet.
Compared with other microcontrollers, the PIC16F87X family has a few notable differences with respect to
interrupt processing.
1. Only one interrupt vector is used. Your ISR must determine (through status bits) which subsystem
generated the interrupts.
2. Context of the CPU is not saved, except for the return Program Counter. Your ISR must be written to
compensate for this.
3. Each interrupt uses one internal stack location until processing is complete. Only 8 stack locations are
available and subroutine calls also use them. Due to this limitation, use of nested interrupts is
discouraged. However, nesting is disabled by default.
Below is a very simple program that is used to show the necessary components for an assembly program.
Also, MPLAB contains source code templates (f873temp.asm and f877temp.asm), which can be found in
mplab/template/code/. You can use these as a starting point.
;************************************************************
;
*
;
This is a program header. Here you give a brief
*
;
description of what your program does and any other
*
;
important information about it. You should include
*
;
the name of the program, your name, the date you
*
;
wrote the program and/or the last date it was
*
;
modified. Include a course name if applicable.
*
;
*
;
name: example.asm
(program name)
*
;
date: 9 July 2002
(date created)
*
;
created by: David R. Bull
(thats me)
*
;
course: EE401
*
;
*
;
This program doesnt do anything (since there are no *
;
instructions in the main program). It is just used
*
;
to illustrate the necessary components of an assembly *
;
language program for the PIC microcontroller.
*
;
*
;************************************************************
list
p=16f873
#include <p16f873.inc>
;
;
;
;
;
;
;
;
;
;
;
;
;
The following commands set the PICs configuration bits. For now
you dont really need to understand how the configurations bits
affect anything, but if you really want to see section 12.1 in the
PIC16F87X data sheet.
You can also set the configuration bits manually when you are
downloading your program to the PIC (see section 4.1)
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _XT_OSC &
_WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF
; Label Definitions
TEMP1
TEMP2
EQU
EQU
0x20
0x21
BANK0
BANK1
BANK2
BANK3
EQU
EQU
EQU
EQU
0x0000
0x0080
0x0100
0x0180
page0
page1
page2
page3
EQU
EQU
EQU
EQU
0x0000
0x0800
0x1000
0x1800
0x00
clrf
goto
PCLATH
main
;
;
;
;
;
;
;
;
;
0x04
goto
service
;
;
;
;
The source code for some example programs are available on the EE401 website. It may help to take a
quick look at the code to become more familiar with the contents of an assembly language program.
Open MPLAB
Open your source code file (debug87x.asm)
In the Project menu select Build Node
And thats it. A new window will open that shows the results of the process. If your source code is error
free the message Build Completed Successfully. will appear in this window. Assembling generates a
*.hex file (in this case it will be debug87x.hex) and places it in the same directory as your source code file.
This is the file that you will download to the PIC microcontroller. You can also download the *.hex files
from the EE401 website.
If there are errors in your code then this window will contain the appropriate error messages.
1.
2.
3.
Open MPLAB
Ensure that the PICSTART Plus is connected to the
computer and that the power cord is plugged in.
Put your PIC chip in the uppermost position in the
socket on the PICSTART Plus, with the notch on
the PIC pointing to the top.
Figure 4.1
5.
6.
7.
Figure 4.2
Figure 4.3
8.
Finally, click the Program button to burn your program to the PIC. You will receive a message
notifying you if the program was transferred to the PIC successfully. Take the PIC out of the
programmer, plug it back into your MicroBoard, and youre ready for business.
Part III
The MicroBoard In Action
5.0 Debug87x
When the MicroBoard is running debug87x.hex you can control many of its functions through a serial link
to a personal computer. HyperTerminal (or other terminal program) is used to communicate with the
MicroBoard in a command-prompt fashion. Using and configuring HyperTerminal is very easy, just follow
these steps:
1.
2.
3.
4.
5.
6.
7.
8.
9.
You should now see a window before you that is blank and has a blinking cursor in the upper left corner.
Connect your MicroBoard to the PC using a computer serial cable. Then connect the MicroBoard to the
power supply.
If your MicroBoard is working properly a help menu will appear in this window. This help menu provides
you with a list and brief description of the commands used to control the different MicroBoard modules.
These commands are also discussed in the following sections of this user manual. To initiate a command
simply type it in at the prompt and press ENTER. Debug87x ignores uppercase commands, letters and
hexadecimal numbers.
With hardware flow control enabled you can send a string of commands to the PIC all at once (like a script)
and the PIC will execute the commands in the order they are received (for an example, see section 6.1.6).
If you are using the PIC16F873 the default state for hardware flow control is disabled. See the following
section (section 5.1) for instructions on enabling hardware flow control. If you are using the PIC16F877
hardware flow control is already enabled.
To create a script, simply save to a text file a set of commands in the order you would like them carried out.
Start a HyperTerminal session and select Transfer > Send Text File Choose your saved script. The
commands will be sent to the PIC and executed one by one.
In the future, you may want to use the subroutines in debug87x as part of your own program. If you
modify the contents of debug87x or write your own program from scratch, youll need to compile and burn
the new program to your PIC using the procedure discussed in sections 4.0 and 4.1.
Add two 470 resistors at positions R33 and R34 (beside the MAX232 chip).
Solder a wire from the end of R34 (end closest to DB9 connector) to pin RB1 on the PIC.
Solder a wire from the end of R33 (end closest to DB9 connector) to pin RB2 on the PIC.
Instructions on writing your own assembly language code to control the modules.
Instructions on using debug87x.hex to control the modules.
Writing C programs to control the modules.
Examples to illustrate what you can do with them.
STATUS , RP0
STATUS , RP1
; select bank1
movlw
movwf
B11110000
TRISB
bcf
STATUS , RP0
; select bank0
movf
PORTB , W
movlw
movwf
B1010
PORTB
Each port, and the alternate function(s) of its pins, is discussed in its own section below. Refer to section
3.0 of the PIC16F87X data sheet for additional information on I/O ports.
control bits (the lower four bits of the ADCON1 register). Refer to Section 11.0 (Register 11-2) in the
PIC16F87X data sheet for a table of the A/D port configuration control bits.
For example, to configure all the pins in ports A and E for general purpose digital I/O you must write
B011x (B0110 or B0111) to the lower four bits of the ADCON1 register.
(PIC16F873 only) Pin RA4 has a weak internal pull-up. If you will be using this pin for digital I/O you
must connect an external pull-up resistor.
The analog inputs are used with the Analog-to-Digital Converter (A/D) module. See section 6.7 for
instructions on using the A/D module. The ADON bit (ADCON0<0>) controls whether or not the A/D
module is operating. If you are not using the A/D module then it is recommended that you turn it off by
clearing the ADON bit.
(PIC16F877 only) The three pins in port E also function as control inputs for the Parallel Slave Port (PSP)
module. To disable the PSP module clear the PSPMODE bit in the TRISE register. See section 6.2 for
more information on the PSP.
Data is read from/written to ports A and E using the PORTA and PORTE port registers, respectively. The
data direction registers are TRISA and TRISE.
Table 6.1: Summary of Registers Associated with PORTA and PORTE.
Name
Address
PORTA
0x05
TRISA
0x85
Bit 7
Bit 6
Bit 5
Bit 4
RA5
RA4
PORTE
0x05
TRISE
0x85
IBF
OBF
IBOV
PSPMODE
ADCON0
0x1F
ADCS1
ADCS0
CHS2
CHS1
ADCON1
0x9F
ADFM
Bit 3
Bit 2
RA3
RA2
PORTA data direction bits.
Bit 1
Bit 0
RA1
RA0
RE2
RE1
RE0
PORTE data direction bits.
CHS0
GO/DONE
PCFG3
PCFG2
ADON
PCFG1
PCFG0
The following code shows how ports A and E can be initialized for digital I/O:
bcf
bcf
STATUS , RP0
STATUS , RP1
; select bank0
clrf
clrf
PORTA
PORTE
bsf
bcf
STATUS , RP0
STATUS , RP1
; select bank1
movlw
movwf
b0110
ADCON1
movlw
movwf
movlw
movwf
b111000
TRISA
b001
TRISE
6.1.2 Port B
Three of the pins in Port B are multiplexed with the low voltage programming option. The low voltage
programming option allows PIC microcontrollers to program by one another. Refer to the Special Features
Section in the PIC16F87X data sheet for instructions on using this feature.
Pins RB7:RB4 have an interrupt on change feature, which is discussed in section 12.10 of the PIC16F87X
data sheet.
Pins RB1 and RB2 are reserved for hardware flow control (see section 5.1) and can only be used for digital
I/O if hardware flow control is not being used.
Data is read from/written to port B using the PORTB port register. The data direction register is TRISB.
Table 6.2: Summary of Registers Associated with PORTB.
Name
Address
Bit 7
Bit 6
Bit 5
Bit 4
PORTB
0x06
RB7
RB6
RB5
TRISB
0x86
OPTION_REG
0x81
RBPU
INTEDG
T0CS
Bit 3
RB4
RB3
PORTB data direction bits.
T0SE
PSA
Bit 2
Bit 1
Bit 0
RB2
RB1
RB0
PS2
PS1
PS0
6.1.3 Port C
Port C is shared by many of the peripheral functions, such as the timer modules, the pulse-width-modulator,
the analog-to-digital converter and the serial communication modules. Refer to the corresponding
peripheral section for the appropriate PORTC settings.
Data is read from/written to port C using the PORTC port register. The data direction register is TRISC.
Table 6.3: Summary of Registers Associated with PORTC.
Name
Address
Bit 7
Bit 6
Bit 5
PORTC
0x07
RC7
RC6
RC5
TRISC
0x87
Bit 4
Bit 3
RC4
RC3
PORTC data direction bits.
Bit 2
Bit 1
Bit 0
RC2
RC1
RC0
Address
Bit 7
Bit 6
Bit 5
PORTD
0x08
RD7
RD6
RD5
TRISD
0x88
TRISE
0x85
IBF
OBF
IBOV
Bit 4
Bit 3
RD4
RD3
PORTD data direction bits.
PSPMODE
Bit 2
Bit 1
Bit 0
RD2
RD1
RD0
To set the value of an output pin use the set and clear commands.
>> set b4
>> clear b4
To read the value on one of the inputs use the read command.
>> read c2
Pin=1
The value is displayed in the terminal window as shown above. Here it is assumed that the input pin RC2
is high.
If you connect an LED to one of the I/O pins, say pin RC0, you can turn it on and off using the above
commands. Remember to include a current limiting resistor.
>> output c0
>> set c0
>> clear c0
If you have hardware flow control enabled (see section 5.1) you can use a script to perform the same task.
Simply save the following commands to a text file (do not include the comments on the right).
output c0
set c0
delay 96
clear c0
delay 96
set c0
delay 96
clear c0
delay 96
set c0
etc.
- repeat ad nauseum
In HyperTerminal select the Transfer>Send Text File command and choose your text file. The LED
should be blinking now and will stop when the commands in your script are finished executing.
The delay command accepts a two digit hexadecimal number (hh) and will wait (hh x 10)ms before
executing the next command. It is not terribly useful when you are connected to the MicroBoard through
HyperTerminal since you, as the operator, can wait as long as you like between sending commands. The
delay command is, as illustrated above, useful when sending a script of commands to the MicroBoard.
>> delay 10
>> delay 8f
>> delay ff
Address
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Bit 0
PORTD
0x08
RD7
RD6
RD5
RD4
RD3
RD2
RD1
RD0
PORTE
0x05
RE2
RE1
RE0
PORTE data direction bits.
TRISE
0x85
IBF
OBF
IBOV
PIR1
0x0C
PSPIF
ADIF
RCIF
PSPMODE
TXIF
SSPIF
CCP1IF
TMR2IF
TMR1IF
PIE1
0x8C
PSPIE
ADIE
RCIE
TXIE
SSPIE
CCP1IE
TMR2IE
TMR1IE
ADCON1
0x9F
ADFM
PCFG3
PCFG2
PCFG1
PCFG0
For additional information on using the PSP module see section 3.6 in the PIC16F87X data sheet.
RD7
RA5
RD6
RA4
RD5
RA3
RD4
RA2
RD3
RA1
RD2
RA0
RD1
RB0
RD0
RB3
Connecting a LED to each of these outputs will allow you to visually see the value on each of the pins. The
peripheral device controlling the PSP will be you. Consider the following schematic:
PIC16F877
+5V
RD7
RD6
RD5
RD4
RD3
RD2
RD1
RD0
30
29
28
27
22
21
20
19
+5V
RD
WR
S7
CS
10
S6
S5
S4
S3
S2
S1
S0
Pushbutton
and Voila! You should now see the input value displayed on the outputs.
Lets analyze the source code. The program begins by initializing the PSP module (initializepsp
subroutine). The next subroutine (initializeoutputs) configures the pins RA5-RA0, RB3 and RB0 as
digital I/O outputs and initializes their values to zero.
Data is input in the readpsp subroutine. When the IBF flag bit is set (pushbutton is pressed and released)
the data on the PORTD input pins is read in and stored in a memory location labeled DATAREG. The
displaydata subroutine simply transfers the data from the DATAREG memory location to the appropriate
output pins.
Only the SPI module will be discussed in this manual. For instructions on using the I2C module refer to
section 9.2 of the PIC16F87X data sheet.
PIC16F877
RA3 5
SCK 18
11
SDO 24
12
14
16,10
8,13
9
74HC595
15
+5V
+5V
+5V
11
12
14
74HC595
15
11
8,13
16,10
12
14
+5V
8,13
16,10
74HC595
15
11
12
14
8,13
16,10
74HC595
15
The SPI will be configured in master mode and it will control the clock (SCK). With Vcc=+5V on the
74HC595 the maximum shift register clock frequency is ~25MHz. Assuming the PIC clock frequency
(Fosc) is 4MHz, we can safely set the frequency of SCK to Fosc/4=1MHz. For this setting the
configuration bits SSPM3:SSPM0 (SSPCON<3:0>) must all be cleared.
The waveforms in Figure 9-2 in the PIC16F87X data sheet will be used to decide the configuration of the
CKP (SSPCON<4>) and CKE (SSPSTAT<6>) bits. The shift register clock on the 74HC595 (pin11) is
rising edge triggered so the data on the SDO pin must be stable on the rising edge of SCK. There are two
configurations that satisfy this requirement:
1.
2.
CKP = 1 , CKE = 0
CKP = 0 , CKE = 1
The only difference between these two configurations is that in the first configuration the clock idle value is
high and in the second configuration the clock idle value is low. The clock idle value is not important in
this case so either configuration will do. The first one will be used in this example.
Pin RA3 on the PIC16F877 is configured as a digital I/O output and will be used to send a pulse to update
the shift registers. Data shifted into the shift registers does not appear on the output pins until a pulse is
received on the register clock input pin (pin 12 on 74HC595).
The example program addouts.asm begins by defining four constants: BYTE1, BYTE2, BYTE3 and
BYTE4. These values of these constants were arbitrarily defined and these values will be output to the four
shift registers, starting with BYTE1.
The main program begins with a call to the initializespi subroutine. This subroutine initializes and enables
the SPI module in the configuration discussed above. The initializeRA3 subroutine that follows simply
configures pin RA3 as a digital I/O output and initializes the value to zero.
Next the four bytes of data are transmitted using the sendbyte subroutine. This subroutine begins by
clearing the interrupt flag bit SSPIF. The data transfer is accomplished by writing the value from the W
register to the SSPBUF register. Note: the appropriate value must be loaded to the W register before the
call to the sendbyte subroutine is made.
Since there are four consecutive calls to this subroutine (only one byte is sent at a time) we make sure that
the transfer is complete before control is given back to the main program. This is accomplished by polling
the interrupt flag bit SSPIF. When the SSPIF bit is set (signaling the transfer is complete) the return
command is executed and the main program resumes.
After the four bytes are transmitted the output pin RA3 is pulsed to update the outputs of the shift registers.
You can now measure the voltages on the output pins to confirm that the program has executed properly.
In this example the SPI input pin (SDI) is not used. In a similar fashion an additional number of input pins
can be added using the SPI and some parallel load shift registers (74HC165). This would require the use of
the SPI input pin (SDI).
Here it is assumed that there is an SPI device connected to the input of the SPI module, which sends the
hex byte 0x92.
Consider the example in the previous section (section 6.4.2). Using the configuration shown in Figure 6.2
we can send data to the shift registers using the following commands. Lets also assume that we have
grounded the SPI input pin since it is not being used.
>> spiinit
>> output a3
>> clear a3
>> spitrans 45
val=00
>> spitrans a9
val=00
>> spitrans 05
val=00
>> spitrans ff
val=00
>> set a3
>> clear a3
Make sure that the LCD is connected to your MicroBoard before executing this command. You should see
the following text on the display.
EE 401
U. of Alberta
If there is nothing on the display reverse the connection and execute the lcdinit command again. If it still
doesnt work seek assistance from your TA.
>> lcdclear
>> lcdput line1
>> lcdline2
>> lcdput line2
>> lcdline1
See the example source code (lcd_ex.c available only for the PIC16F877 MicroBoard) found in the PIC
Code section of the EE401 website. This program also writes text to a terminal window on a PC (see
section 6.5.2).
Comparing the % error for these two setting we see that the second configuration has a lower % error (0.16
as opposed to 6.99). We will use this configuration.
The mode of communication is Asynchronous since there is no clock signal. Instead start and stop bits are
used. When asynchronous mode is selected the USART automatically attaches start and stop bits to the
data.
We will only be sending byte size data chunks so 8-bit transmit and receive is selected. Hardware flow
control will be used. Interrupts are disabled.
Now open and configure HyperTerminal with the following settings (refer to section 5.0 if necessary).
1.
2.
3.
4.
5.
You should have a window before you that is blank and has a blinking cursor in the upper left corner. It
looks pretty boring but this window is where all of the action happens. When you push a button on the
keyboard, the 8-bit ASCII value of the character you typed is sent to your MicroBoard. Data received by
HyperTerminal is written in this window.
For this example it is necessary to change some of the advanced properties of Hyperterminal. To do so
follow these steps:
1.
2.
3.
4.
5.
6.
Check the box beside Send line ends with line feeds. Now when you hit ENTER both a
carriage return and line feed are sent. A carriage return moves the cursor to the beginning of the
line and a line feed moves the cursor to the next line.
Click OK.
Click OK.
Lets analyze the example source code. The program begins by initializing the USART in the
configuration discussed above (initializeusart subroutine). Next the program sends the prompt Type
something..: to the HyperTerminal window using the writeprompt subroutine. The writeprompt
subroutine sends the prompt string to the HyperTerminal window one character at a time using the
outputbyte subroutine.
The outputbyte subroutine works in the following way. It first checks to see if the PC is ready to receive
data by testing the value on RB1. This pin is low when the PC is ready. Then it checks if the input buffer
is empty by testing the TXIF flag bit. If the buffer is full, then it waits until it is empty before it continues.
If it is empty the byte in register W is written to the TXREG register (USART transmit register). Note that
to send the desired character you must load its ASCII value into the W register before calling the
outputbyte subroutine.
After writing the prompt the program calls the inputbyte subroutine, which functions as follows. First the
CTS_PIN (RB2) is set low to enable reception. At this point the PC will start sending data. When the
RCIF flag bit is set (the receive buffer is full) reception is disabled and the byte in the receive buffer is
moved to the W register.
Next a call to the outputbyte subroutine is executed to send the received character to the terminal window.
The program loops through the consecutive inputbyte and outputbyte subroutines, effectively receiving a
character from HyperTerminal then immediately sending it to be displayed in the terminal window. So
anything that you type will appear on the screen. Pressing the enter key will jump the cursor to the
beginning of the next line.
See the example source code (lcd_ex.c or rs232.c) found in the PIC Code section of the EE401 website.
This program also writes text to an LCD (see section 6.4.5).
You have control over the value in the PR2 register (Timer2 modules register) and the TMR2 prescale
value. PR2 holds an 8-bit number and TMR2 prescale value can be either 1, 4 or 16. TMR2 prescale value
is set using the T2CKSP1:T2CKSP0 bits (T2CON<1:0>). See section 7.0 (Register 7-1) in the PIC16F87X
data sheet. Tosc is the oscillator period (0.25 s).
For example, if PR2 contains B01100111 = 103 and T2CKSP1:T2CKSP0 = B01 (prescale = 4) then the
PWM period is (103+1)*4*0.25*4 = 416 s.
The duty cycles are specified with a 10-bit number. Each PWM pin has an associated CCPRxL register and
CCPxCON register. The CCPR1L register holds the upper 8 bits of the duty cycle value for CCP1 and
CCP1CON<5:4> holds the lower 2 bits. For CCP2 the CCPR2L and CCP2CON registers are used. The
following equation defines the PWM duty cycle:
DutyCycle = (CCPRxL : CCPxCON < 5 : 4 >) Tosc (TMR 2 prescale)
For example, if CCPR1L contains B00110011 and CCP1CON<5:4> contains B10 the duty cycle for
CCP1 is 206*0.25*4 = 206 s.
See the PIC Code section of the EE401 website for sample code (testpwm.asm).
Note: On the PIC, pin RC2 corresponds to PWM output pin CCP1 and pin RC1 corresponds to pin CCP2.
>>
>>
>>
>>
>>
pwmperiod ff
pwmduty1 40
pwmduty2 7f
pwmstop1
pwmstop2
If you connect an LED to one of the PWM outputs, you can vary the brightness through varying the duty
cycle.
Choosing appropriate values for the resistance and capacitance forms a low pass filter with the necessary
time constant for creating an analog signal from the PWM output. The values shown are merely a
suggestion; youll need to make sure that the PWM period is sufficiently short compared to the RC time
constant or ripple will be evident. The output of this signal is controlled by the duty cycle of the PWM
signal: to increase the voltage, increase the duty cycle and vise versa.
>>
>>
>>
>>
>>
startpwm
pwmperiod ff
pwmduty1 00
pwmduty1 80
pwmduty1 ff
After running adcinit all the A/D inputs are enabled. That is, you can no longer use these pins for general
purpose digital I/O. Running either the input or output commands on one of the A/D inputs will
automatically turn the A/D module off.
Part IV
Appendices
Description
100F 25V electrolytic radial lead (100-220F 25V or greater)
001F 50V mono-cap
10F 25V electrolytic radial lead (10-22F 25V or greater)
01F 50V mono-cap
2.1mm barrel power connector
9 pin female right angle DB connector
1N4000 1A 50V rectifier (1N4000-1N4007)
LM7805 5V 1A TO-220 voltage regulator
PIC16F873-04
L293 dual H-bridge driver
MAX232A RS-232 interface chip
4K7 watt resistor
470 watt resistor
330 watt resistor
4.00MHz 3 pin ceramic resonator with integral capacitors
14 pin IC sockets
16 pin IC sockets
Red LED
9Vdc 500ma wall adapter
MicroBoard Printed Circuit Board
Part Number
C1
C2, C5, C7, C17, C22, C23
C3 & one for test
C24-C28
CN1
CN6
D1
IC1
IC4
IC5
IC8
R1, R29, R30 & one for test
R23, R24 & one for test
R31, R32
Y1
Sockets for IC4
Sockets for IC5 and IC8
one for test
A2 Assembly Checklist
Soldering the components in this order is recommended (check them off as you go).
Part
Description
Number
4K7 watt resistors
R1
Notes
Yellow Violet Red Gold
R29
R30
470 watt resistors
D1
1N400x
Sockets
Socket
Socket
Y1
CN1
CN6
C1
100F 25V
C3
10F 25V
IC1
LM7805
R23
R24
R31
R32
C24
C25
C26
C27
C28
C2
C5
C7
C17
C22
C23
A5 - Power Checklist
Before installing any ICs, test the board for proper power connections.
The following measurements are to be taken on the auxiliary power connector. Before connecting the
power perform the following measurement.
Measurement
Use a DMM to measure resistance and check for a short
circuit from Vcc to ground.
Probe Connection
Desired Value
> 500K
Now plug in the wall adaptor and connect it to CN1 (2.1mm barrel connector). Measure the following:
Vcc (with reference to ground)
+5Vdc
Voltage on MCLR
+5Vdc
Supply voltage
+5Vdc
Vcc
+5Vdc
ENA voltage
+5Vdc
ENB voltage
+5Vdc
+5Vdc
If, and only if, all of the above power checks are correct continue. Disconnect the power and insert the
MAX232 IC into its socket. Pay careful attention to its orientation since connecting it backwards will
likely destroy the chip. Power up the MicroBoard again and measure the following on the MAX232
socket:
Supply voltage
+5Vdc
+10 V supply
+10Vdc
-10 V supply
-10Vdc
The power check is now complete. If all of your measurements were as expected then everything should
work fine. You can insert the other ICs into their appropriate sockets and you are ready to program the
PIC.
Description
100F 25V electrolytic radial lead (100-220F 25V or greater)
10F 25V electrolytic radial lead (10-22F 25V or greater)
01F 50V mono-cap
1
1
1
1
1
1
1
4
30
1
1
2
1
1
1
Part Number
C1
C3 & one for test
C2, C5, C7, C15, C18, C19,
C24-C28
CN1
DB09
D1
IC1
IC4
IC6
IC8
R1, R25, R26 & one for test
R10-R13, R23, R27-R30,
R35-R38, R43 -R48, R52,
R54, R56-R64
Y1
Socket for IC4
Sockets for IC6 and IC8
one for test
B2 - Assembly Checklist
Soldering the components in this order is recommended (check them off as you go).
Part
Description
Number
4K7 watt resistors
R1
Notes
Yellow Violet Red Gold
R25
R26
R35
R47
R43
R38
R11
R10
R12
R13
R36
R45
R37
R44
R54
R52
R56
R64
R57
R63
R58
R62
R59
R61
R60
R46
R30
R48
R29
R28
R27
R23
C2
D1
1N400x
Socket
Socket
Socket
Y1
CN1
CN6
C1
100F 25V
C3
10F 25V
IC1
LM7805
C5
C7
C15
C18
C19
C24
C25
C26
C27
C28
B5 - Power Checklist
Before installing any ICs, test the board for proper power connections.
The following measurements are to be taken on the auxiliary power connectors (labeled RAW and VCC,
see board layout diagram). Before connecting the power perform the following measurement.
Measurement
Probe Connection
Desired Value
VCC connector
> 500K
RAW connector
> 500K
Now plug in the wall adaptor and connect it to CN1 (2.1mm barrel connector). Measure the following:
Raw Supply
RAW connector
VCC connector
+5Vdc
Voltage on MCLR
+5Vdc
Supply voltage
+5Vdc
Supply voltage
+5Vdc
Ground
0Vdc
Vcc
+5Vdc
ENA voltage
+5Vdc
ENB voltage
+5Vdc
+5Vdc
If, and only if, all of the above power checks are correct continue. Disconnect the power and insert the
MAX232 IC into its socket. Pay careful attention to its orientation since connecting it backwards will
likely destroy the chip. Power up the MicroBoard again and measure the following on the MAX232
socket:
Supply voltage
+5Vdc
+10 V supply
+10Vdc
-10 V supply
-10Vdc
The power check is now complete. If all of your measurements were as expected then everything should
work fine. You can insert the other ICs into their appropriate sockets and you are ready to program the
PIC.
3.
Use the hot soldering iron at a 45 angle. The irons tip should come in contact with both the
component lead and the pad on the circuit board. Allow the lead and pad to heat up (a few
seconds).
4.
5.
6.
7.
Apply the solder to the heated lead and allow it to heat the solder. Try not to touch the solder to
the soldering iron. Allow the solder to melt and spread around the whole connection. After the
solder flows around and adheres to the part being connected remove the soldering iron.
Examine the solder connection. If the connection is cone shaped the proper temperature was
reached; bad solder appears grayish and round.
Cut the components wire leads, leaving a bit of wire protruding from the solder.
Examine the area around and remove any excess solder.