ECE 3724/CS 3124 Microprocessors I Lab Manual

advertisement
ECE 3724/CS 3124
Microprocessors I
Lab Manual
© R. B. Reese
Preface
The goals of these lab experiments are simple; to expose you to a range of topics in
microprocessor assembly language programming and hardware interfacing. The
PIC18F242 is used as it is supported by freely available development tools from
Microchip (MPLAB IDE, assembler and simulator) and high quality C compilers
(Hi-Tech Software, the PIC18 C Compiler). The availability of PICs in small pin
count DIP packages with on-chip USART, I2C, and A/D modules make it easy to
build a small protoboard system that is used to support a wide variety of relevant
exercises.
Experiments 1 and 2 relate basic digital design to the microprocessor world. The
next three experiments introduce PIC assembly language programming and the connection between assembly language and C programming. Experiments 6 through 13
build a PIC18F242 system from scratch to explore topics such as RS232 interfacing, the I2C bus, A/D and D/A conversion, interrupt driven IO, IR pulse width
decoding, and audio record/playback. The experience of building a microprocessor
system from the ground up provides skills that prove useful in later design experiences, such as the capstone senior design course.
These labs assume a basic digital design course prerequisite (ECE 3714), exposure
to C or C++ programming, and familiarity with the Altera Maxplus toolset (used in
the first two lab exercises). A physics-level circuits theory exposure is all that is
needed to succeed in the hardware labs. An oscilloscope and multimeter are used in
the hardware experiments. The parts kit cost is approximately $50 and can be purchased through the department; the lab web site has the complete parts list posted.
The protoboard purchased previously for ECE 3714 is used throughout the semester
to build the PIC-based system. The board must stay wired between lab exercises, so
if you have another lab that requires a protoboard then a second protoboard must be
purchased. You may also find it necessary to purchase an extra wiring kit. All of the
C and assembly language programs referenced in this document are available from
the lab web site (http://www.ece.msstate.edu/~reese/ece3724/lab).
The material in this document is intended to supplement material in the textbook
and datasheets. Refer to the lab web site for a detailed lab schedule and lab report
guidelines. If errata is found in this lab manual, please send email to
reese@ece.msstate.edu. Feel free to send comments about clarity, difficulty or any
other topic concerning the exercises to the same email address! Send any comments
about the Knuts & Boltz strips at the start of each exercise to my evil twin whose
email address is bots@insightbb.com (FYI: yes, he is my twin but is really not evil;
he is an ex-F15 fighter pilot with an MSEE degree who after 20 years in the Air
Force currently flies boxes for UPS in-between drawing Knuts & Boltz strips, see
http://www.b0ts.com -- that is a zero in b0ts).
Many thanks goes to J. Harden, J.W. Bruce, and J. Moorhead for discussions and
suggestions.
Good luck, and I hope your lab experience is a good one.
R. B. Reese 5/2004
Summer 2004/V0.2
i
Contents
Experiment 1: A Stored Program Machine- - - - - - - - - - - - - - - - - - - - - 1-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-2
Finite State Machine versus Stored Program - - - - - - - - - - - - - - - - 1-2
The Problem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-3
A Stored Program Computer - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-4
What instructions are needed? - - - - - - - - - - - - - - - - - - - - - - - - - - 1-5
Instruction Encoding - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-6
The Hardware - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-8
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-11
Background - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-11
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-11
Maxplus LPMs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-12
Changing a Parameter Value - - - - - - - - - - - - - - - - - - - - - - - - - - 1-12
LPM_DFF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-12
LPM_COUNTER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-13
LPM_ROM - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-13
MIF format - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-13
Bus Labeling - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1-14
Experiment 2: The PIC 18Fxx2 Architecture - - - - - - - - - - - - - - - - - - - 2-1
PreLab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-2
A quick introduction to MPLAB - - - - - - - - - - - - - - - - - - - - - - - - 2-2
Simulating your program - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-3
Single Stepping - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-4
Reset, Clearing Memory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-5
QuickBuild Mode instead of Projects - - - - - - - - - - - - - - - - - - - - - 2-5
Watch Window - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-5
Animate Command - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-5
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-6
Exploring PIC18 Data memory organization - - - - - - - - - - - - - - - - 2-6
Data Memory Banks in the PIC18 - - - - - - - - - - - - - - - - - - - - - - - 2-6
Moving data between banks - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-9
showid.asm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-10
bit test and skip - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-10
Controlling the value of odd - - - - - - - - - - - - - - - - - - - - - - - - - - 2-10
The Stopwatch - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-10
A poor emulation? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-11
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2-12
Experiment 3: PIC18Fxx2: Instruction Set- - - - - - - - - - - - - - - - - - - - - 3-1
Summer 2004/V0.2
ii
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-2
A Quick C Review - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-3
Loops and Conditions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-4
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-6
STATUS Register: Carry, Zero Flags - - - - - - - - - - - - - - - - - - - - - 3-6
Converting the C operations to PIC Assembly - - - - - - - - - - - - - - - 3-7
arithmetic operations - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-8
logical operations - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-8
Shift operations - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-8
Condition Tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-10
Test for bit set or clear - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-10
Zero/Nonzero Test with branch instruction - - - - - - - - - - - - - - - - 3-11
Zero/Nonzero Test with branch instructions - - - - - - - - - - - - - - - - 3-12
<, > tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-13
Compare instructions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-15
Equality, Inequality tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-16
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3-17
Experiment 4: Data: Wider is Better - - - - - - - - - - - - - - - - - - - - - - - - - 4-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-2
Data Sizes in C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-3
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-5
Storing 16-Bit values in memory - - - - - - - - - - - - - - - - - - - - - - - - 4-5
Addition/Subtraction of 16-bit values - - - - - - - - - - - - - - - - - - - - - 4-7
increment, decrement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-7
left, right shift - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-8
Unsigned 16-bit comparisons - - - - - - - - - - - - - - - - - - - - - - - - - - 4-10
16-bit Equality tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-11
16-bit Zero/Nonzero tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-11
Signed Comparisons - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-12
Integer Signed Comparison: N, V flags - - - - - - - - - - - - - - - - - - - 4-13
Equality, zero, nonzero tests for 16-bit signed data - - - - - - - - - - - 4-15
PC Relative Addressing - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-15
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4-17
Experiment 5: Beyond Assembly Language- - - - - - - - - - - - - - - - - - - - 5-1
Prelab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-2
Pointers in C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-2
Pointers in PIC assembly language - - - - - - - - - - - - - - - - - - - - - - - 5-3
Subroutine Parameters - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-4
main code - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-5
strcnt subroutine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-5
POSTINC0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-6
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-9
Compiling C programs to PIC18 machine code - - - - - - - - - - - - - 5-10
Simulating cstrcnt.c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-12
Compiling, Simulating your C program - - - - - - - - - - - - - - - - - - - 5-13
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-14
Summer 2004/V0.2
iii
Formal Report Questions - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5-14
Experiment 6: Bringing the PIC to Life - - - - - - - - - - - - - - - - - - - - - - - 6-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6-4
Which pins are Tx and Rx? - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6-6
Detailed RS232 Serial Port Debugging - - - - - - - - - - - - - - - - - - - - 6-7
What is next? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6-9
Optional In-Circuit Programming Connection - - - - - - - - - - - - - - 6-14
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6-15
Experiment 7: Serial versus Parallel - - - - - - - - - - - - - - - - - - - - - - - - - 7-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7-3
Formatted IO via printf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7-5
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7-7
Experiment 8: Interrupt-Driven IO - - - - - - - - - - - - - - - - - - - - - - - - - - 8-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8-3
The Overrun Problem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8-7
Fixing the Problem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8-7
Storing/Retrieving values from a circular buffer - - - - - - - - - - - - - - 8-7
Empty, Not-empty, Full - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8-8
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8-9
Experiment 9: Memory and the I2C Bus - - - - - - - - - - - - - - - - - - - - - - 9-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-3
Streaming writes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-4
Use two buffers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-4
Checking for Overrun - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-6
Program Operation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-7
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9-8
Experiment 10: Talking to the Real World- - - - - - - - - - - - - - - - - - - - -10-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10-3
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10-6
Formal Report Questions - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10-6
Experiment 11: Controlling Time- - - - - - - - - - - - - - - - - - - - - - - - - - -11-1
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11-4
sqwave.c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11-4
ledpwm.c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11-5
sinegen.c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11-7
Comments on sinegen.c measurements - - - - - - - - - - - - - - - - - - - 11-8
Arbitrary Waveform Generation - - - - - - - - - - - - - - - - - - - - - - - - 11-9
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11-12
Experiment 12: Time Measurement - - - - - - - - - - - - - - - - - - - - - - - - -12-1
Summer 2004/V0.2
iv
Prelab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-2
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-3
swdet.c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-3
Multiple Timer1 Overflows - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-4
IR Pulse Decoding - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-5
‘1’,’0’, Start periods - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-6
Hints for IR Decoding - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-7
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12-10
Experiment 13: The PIC Listens and Speaks - - - - - - - - - - - - - - - - - - -13-1
PreLab Requirements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13-2
Audio Sampling - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13-3
Lab Activity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13-5
Implementing Playback - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13-5
Report - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13-7
Appendix A: Prototyping Hints - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-1
Protoboard and Parts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-2
Protoboard Layout - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-2
Power Connector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-3
Voltage Regulator (7805) - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-3
PCB Fuse - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-4
Resistor SIP Packages - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-4
Capacitors (1.0 µF/0.1 µF) - - - - - - - - - - - - - - - - - - - - - - - - - - - A-4
Light Emitting Diodes (LEDs) - - - - - - - - - - - - - - - - - - - - - - - - - A-5
Power LED - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-5
Power Switch - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-6
Momentary Pushbutton Switches - - - - - - - - - - - - - - - - - - - - - - - A-6
7.3828 MHz Crystal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-6
Potentiometers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-7
Audio Connector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-8
Wire Wrapping - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-8
Get a decent protoboard! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-9
Get a multimeter! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-10
Debugging - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A-11
My board used to work and now it doesn’t! - - - - - - - - - - - - - - - A-11
My fuse keeps blowing, my board used to work, help! - - - - - - - - A-11
My RS232 interface does not work and/or serial bootloader does not work. A12
My I2C interface does not work. - - - - - - - - - - - - - - - - - - - - - - A-13
My PIC seems to be spontaneously resetting?! - - - - - - - - - - - - - A-13
My A/D input does not work? - - - - - - - - - - - - - - - - - - - - - - - - A-14
Appendix B: Instrumentation- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - B-1
TDS 210 Oscilloscope - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Displaying a continuous waveform - - - - - - - - - - - - - - - - - - - - - Voltage/Time Scaling - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Measure Function - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
B-1
B-1
B-2
B-2
Summer 2004/V0.2
:
Cursor Function, measuring voltage difference, pulse width - - - - Trigger Function, continuous or single shot capture - - - - - - - - - - AC vs. DC Coupling - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Multimeter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Measuring Voltage - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Measuring Resistance - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Measuring Current - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
B-3
B-3
B-4
B-5
B-5
B-5
B-6
—v
:
— vi
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 1: A Stored Program Machine
1
A Stored Program Machine
There was this guy named Von Neuman who hated wiring a new circuit
every time he had a new problem to
solve (kinda like students in the
logic gates class). So, because of
this hatred of wires, the stored
program machine was born. It lives
to fetch and execute all day long,
and sometimes, if we are lucky, we
can make it do useful work for us.
The best thing is that we don’t have
to change any wiring when we want
it to do something different!
Summary
Use a stored program machine approach to implement
a state machine that displays a number sequence.
1—1
Experiment 1: A Stored Program Machine
Summer 2004/V0.2
A. Prelab Requirements
Table 1–1: Prelab Checkoff
Do This
1.
Review the notes below on the Student-ID CPU
machine.
2.
Have Altera Maxplus 10.1+ Baseline edition installed
on your PC and review how to compile/simulate
designs within Maxplus. Perform the Maxplus tutorial
found in the digital devices (ECE 3714) textbook if a
review of Maxplus operation is needed.
3.
Download the file archive containing the Student-ID
CPU. Compile the design in Altera Maxplus, and
verify that you can simulate it. The scpu.gdf Altera
Maxplus schematic in the ZIP archive attached to this
lab is the student ID CPU implementation
4.
Become familiar with the LPM modules used within
the Student-ID CPU design (lpm_counter, lpm_rom,
lpm_dff). Read the material at the end of this lab on
LPM usage within Maxplus.
Finite State Machine versus Stored Program
1—2
Comments
More notes on this subject
are linked to the lab web
site.
The rom.mif file specifies
the memory contents (i.e,
the program); if this file is
changed the schematic
must be recompiled. The
rom.mif file can be edited
with a text editor such as
notepad or wordpad.
In the digital devices course, a logic network was
designed to implement a student ID sequencer. The
logic design used flip-flops and combinational logic to
implement a specific number sequence. A different
student ID required a different logic design. An alternate approach to solve this problem uses a general purpose logic network called a stored program machine.
The operation of a stored program machine is determined by instructions stored in a memory. Changing
the instruction sequence (changing the contents of
memory), changes the actions of the machine. A new
problem is solved by simply reprogramming memory;
no hardware modifications are required. This general
purpose logic network might not be as fast as a special
Summer 2004/V0.2
Experiment 1: A Stored Program Machine
purpose logic network, but the flexibility of being able
to solve multiple problems by changing memory contents is often worth this trade-off.
The Algorithmic State Machine (ASM) chart below
illustrates the problem to be solved. The machine displays either the odd or even digits of a student ID. A
single input called odd determines if the odd or even
sequence is displayed.
0
odd?
1
Dout = 4
The Problem
S0
Dout = 5
Dout = 8
Dout = 0
Dout = 2
Dout = 8
S1
S4
Dout = 7
S5
Dout = 1
S2
S6
Dout = 9
S3
S7
Figure 1.1
ASM Chart for Student ID 458 70 2198
The finite state machine implementation shown below
m
n
Combinational
Logic
Circuit
Inputs
k-bit
Present State
Value
k
Memory
Element
Outputs
Figure 1.2 FSM
Block Diagram
k-bit
Next State
Value
k
1—3
Experiment 1: A Stored Program Machine
Summer 2004/V0.2
requires three D flip-flops (k=3) to implement the
eight states of the ASM, one input signal (n=1) to
implement odd, and four output signals (m = 4) to display the current student ID digit (the values 0-9 are
encoded in 4 bits). A new digit is displayed every
clock cycle. A different student ID requires redesign of
the combinational logic network that produces the output value and next state value.
A Stored Program Computer
Figure 1.3
A Stored program
machine
A more general approach solves the problem via a
stored program approach. The block diagram of a
stored program machine (a computer) is shown below.
Address bus
C
o
n
t
r
o
l
Databus bus
Memory
Input/Output
devices
A stored program machine has three principle blocks:
• Memory: stores data and instructions. The memory
contents determines the machine’s actions. The
address bus specifies a particular location in memory, and the data bus contains the data fetched from
or stored to that location.
• Control: logic that controls the fetch and execution
of instructions stored in memory.
• Input/Output: used for interaction with the external
world.
The input/output signals for our stored program
machine are the same as for the finite state machine;
1—4
Summer 2004/V0.2
Experiment 1: A Stored Program Machine
one input for odd and a four bit output bus for displaying the current digit of the student ID.
A stored program machine executes a program that is
stored in memory. A program consists of a sequence of
instructions. The key design question is “What instructions are needed to solve this problem?”. To answer
this, transform the ASM chart to a pseudo high-level
language description as shown below (translation:
something that looks like C or Pascal or any other programming language you know).
What instructions are
needed?
start:
if (odd == 1) then goto odd_start
even_start:
output even digit #1
output even digit #2
....
output last even digit
goto start
odd_start:
output odd digit #1
output odd digit #2
....
output last odd digit
goto start
In the above ‘program’, there are three different operations:
• out data: output a 4-bit value representing the current digit (i.e, ‘output odd digit #2’)
• jmp location: unconditionally jump to a location
(i.e, ‘goto odd_start’). To ‘jump’ to a location
means to fetch the next instruction from that loca-
1—5
Experiment 1: A Stored Program Machine
Summer 2004/V0.2
tion instead of the location immediately following
the current instruction.
• jc location: conditionally jump to location (i.e. ‘if
odd == 1 then goto odd_start’).
Instruction Encoding
The three instruction types above must be encoded in a
binary form for efficient implementation in digital
logic. Typically an instruction is divided into at least
two parts:
• opcode: specifies the instruction type. In this case,
there are three instruction types, so two bits are sufficient for opcode specification.
• data: every instruction operates on data. The data
for the out instruction is the four bits that specifies
the current ID value. The data for the jc and jmp
instructions is the address of the memory location
being jumped to. The number of bits required
depends on the maximum number of locations in
memory. If memory is limited to 16 locations, then
four bits are sufficient to specify a memory location.
The instruction format requires two bits for opcode,
and four bits for data as shown below. The term mne-
Figure 1.4
Instruction mnemonics vs. encoding
mnemonic
encoding
JMP location
00
|
4-bit location
JC location
01
|
4-bit location
10
|
4-bit data
OUT data
b5 b4
b3 b2 b1 b0
monic refers to the human-readable form of the
instruction; the encoding is the binary form of the
instruction that is stored in memory. Each instruction
1—6
Summer 2004/V0.2
Experiment 1: A Stored Program Machine
requires 6 bits. The encoding choice for the opcode
affects the boolean logic required to decode the
instruction. This encoding allows bit b5 to differentiate
an out instruction from the two jump instructions.
The pseudo code written previously for the ASM is
written using these instructions in Table 1–2. Note that
Table 1–2: Program for Student ID 458 70 2198
Memory
Location
Memory
Contents
mnemonic
00
01 0111
start: jc odd_start (loc 7)
01
10 0100
out 4
02
10 1000
out 8
03
10 0000
out 0
04
10 0010
out 2
05
10 1000
out 8
06
00 0000
jmp start (loc 0)
07
10 0101
odd_start: out 5
08
10 0111
out 7
09
10 0001
out 1
0A
10 1001
out 9
0B
00 0000
jmp start (loc 0)
this program almost fills available memory as the four
bit data field for the jc and jmp instructions limit memory to 16 locations. The process of converting the
instruction mnemonic to its binary form (machine
code) is called assembly; typically a computer program called an assembler is used to perform this process automatically. A program written using the
instruction mnemonics of a stored program machine is
called an assembly language program.
1—7
Experiment 1: A Stored Program Machine
The Hardware
Summer 2004/V0.2
The stored program machine is implemented using the
following components:
• Memory: a 16 x 6 memory. The K x N notation for
memory indicates the memory has K locations,
with each location containing N bits.
• Registers: recall from your digital devices course
that a register is used to store a N-bit binary value,
where N is the number of bits in the value. This
machine needs two registers: out and program
counter (PC). The out register is 4-bits wide and
contains the current digit being displayed. The program counter contains the address of the current
location accessed from memory. The PC is implemented as a counter that is either incremented to
point to the next location, or loaded from the data
field of the current instruction to implement the
jump instructions.
• Decode logic: this logic controls the loading of the
out register, and the loading or incrementing of the
program counter. The inputs to the control logic are
the odd input, and the opcode of the current instruction.
1—8
Summer 2004/V0.2
Experiment 1: A Stored Program Machine
Figure 1.5 shows a block diagram of the stored program machine implementation.
Data[3:0]
odd
D
E
C
O
D
E
ld
R
E
G
aclr
out
4
clk
r_ld
Data[3:0]
clk
c_ld
c_en
Op[1:0]
ld
en
aclr
4
c
n
t
r
Addr[3:0]
4
PC
out[3:0]
4
Data[5:0]
M
E
M
6
16 x 6
Data[5:4]
2
Figure 1.5
Stored program machine implementation
The r_ld output of the decode logic controls the loading of the out register, which needs a new value when
an out instruction is executed. The Boolean equation
for r_ld is:
r_ld = op1
as the op1 bit is a logical 1 for an out instruction. The
PC register (the counter) is loaded when a jmp instruction is executed, or if a jc instruction is executed and
the odd input is true. Written as a VHDL statement,
this equation is:
c_ld <= ‘1’ when ((op = ‘00’) or
(op = ‘01’ and odd = ‘1’))
else ‘0’;
Written as a Boolean equation, this becomes:
c_ld = op1’op0’ + op1’ op0 odd
1—9
Experiment 1: A Stored Program Machine
Summer 2004/V0.2
The PC register is incremented if a parallel load is not
done, so:
c_en <= not(c_ld);
c_en = c_ld’;
(VHDL)
(boolean equation)
The aclr control line is an asynchronous reset input; at
power up this input is asserted to clear the PC register
so that the first instruction is fetched from location 0.
1 — 10
Summer 2004/V0.2
Experiment 1: A Stored Program Machine
B. Lab Activity
Background
Table 1–3: Student ID machine Checkoff
Checkpoint
1.
2.
Comments/Debugging
Write a program for the student ID
CPU that outputs the digits of your
student ID. You must have the program represented both as instruction mnemonics and machine code.
Modify the rom.mif file to contain
your assembled program.
Step through the operation of the
student ID CPU with the original
rom.mif file and verify that you
understand what is happening
on each clock cycle.
Create a new schematic called
my_scpu.gdf and make the necessary modifications to it so that it can
support a program that contains up
to 32 lines of code. Test the
changes by placing your original
program starting at location 16 in
memory. At location 0, place a
'goto 16' instruction.
Review the material at the end of
this lab on LPM modules. You
will need to change the width
parameters to one or more LPM
modules and also change the
size of the data busses that connect to them.
Include the instruction mnemonic
as a comment on each line of
machine code in the rom.mif file.
Discuss your proposed changes
with the TA before proceeding
too far into the implementation.
DEMONSTRATE THAT THE CHANGES MADE TO THE
ROM.MIF FILE DISPLAYS YOUR STUDENT ID. DEMONSTRATE THE MODIFIED VERSION OF THE STUDENT ID
MACHINE THAT SUPPORTS 32 INSTRUCTIONS.
C. Report
1. Include the assembly code and machine code of the
programs for checkpoints 1 & 2 of Table 1–3.
1 — 11
Experiment 1: A Stored Program Machine
Summer 2004/V0.2
2. Include a screenshot of your schematic for checkpoint 2 of Table 1–3.
3. Briefly discuss the changes made for the student ID
CPU design for checkpoint 2 of Table 1–3 and the
reasoning behind the changes.
4. Assume a new instruction is needed called 'NOT'
that performs a one's complement (invert the bits)
on the current value in the OUTPUT register. What
changes are required to the decode logic and overall design to implement this? Show a sketch or
rough schematic of the necessary modifications
(there is more than correct solution).
D. Maxplus LPMs
The student ID CPU uses three elements from the
Maxplus Library of Parameterized Modules (LPM).
Each LPM implements a common digital system
building block such as a counter, register, memory, etc.
with parameters used to control key attributes. For
example, each LPM has a parameter called
LPM_WIDTH that determines the component’s data
width (i.e, for a counter, if LPM_WIDTH = 4, then it is
a 4 bit counter). Converting a 4-bit counter to a 16-bit
counter is as easy as changing the value of the
LPM_WIDTH parameter and the labels on the data
busses that connect to the counter.
Changing a Parameter
Value
To change an LPM parameter value, double-click on
the LPM within the schematic to open the Edit Ports/
Parameters window. The lower half of the window
has a scroll list containing all of the parameters. Select
a parameter and edit its value in the Parameter Value
type-in field. Click OK to close the window.
LPM_DFF
The LPM_DFF module is used to implement the out
register. The enable input functions as the load line for
1 — 12
Summer 2004/V0.2
Experiment 1: A Stored Program Machine
the register. The LPM_WIDTH parameter is currently
set equal to 4.
The LPM_COUNTER module is used to implement
the PC register. The sload input is the load signal for
the counter; when asserted the counter is loaded from
the data inputs on the next rising clock edge. The
counter increments its current value on the next rising
clock edge when the cnt_en signal is asserted. The
LPM_WIDTH parameter is currently set to 4.
LPM_COUNTER
The LPM_ROM module is used to implement the program memory (ROM = Read Only Memory). At compilation time, the memory contents are initialized from
the file specified by the LPM_FILE parameter, currently set equal to rom.mif. The LPM_WIDTHAD
parameter specifies the width of the address bus; the
number of locations in the ROM is equal to
2**LPM_WIDTHAD. The current value of
LPM_WIDTHAD is 4, so the number of locations is
2**4 = 16. The LPM_WIDTH parameter controls the
number of bits per location and sets the width of the
output data bus (q[]); it’s value is currently equal to 5.
LPM_ROM
The MIF file, which can be edited with a text editor,
specifies the contents of the ROM. The format is fairly
self-explanatory, but a few words of caution are
needed. The number of locations in the LPM_ROM is
controlled by the LPM_WIDTHAD parameter. A
change to this parameter requires a corresponding
change to the MIF file Depth value that specifies the
number of locations in the ROM. Similarly, a change
to the LPM_WIDTH parameter of the LPM_ROM
requires a corresponding change to the MIF file Width
value. The MIF file does not need a value specified for
every location in the ROM.
MIF format
A comment is bracketed by two ‘%’ symbols; there
MUST BE two ‘%’ symbols! Formatting errors are
1 — 13
Experiment 1: A Stored Program Machine
Summer 2004/V0.2
generated during compilation if an ending ‘%’ symbol
is missing.
Bus Labeling
1 — 14
After changing the LPM_WIDTH parameter on an
LPM, the size of the data busses connected to the LPM
must also be changed by editing the bus label. For
example, assume the LPM_WIDTH parameter of the
LPM_COUNTER is changed from 4 to 5. This
requires modifying the sizes of the busses connecting
to the data[] and q[] pins by changing the bus names
from instr[3..0] to instr[4..0], and pc[3..0] to pc[4..0].
Note these changes affect other busses/components in
the schematic requiring modifications to related
LPM_WIDTH values and bus names as well. Double
click on a bus label to edit it. During compilation, a
“width mismatch” error indicates that the width of the
data bus connecting to an LPM does not match the
internal width of the LPM.
Summer 2004/V0.2
E x p e r i m e n t
Experiment 2: The PIC 18Fxx2 Architecture
2
The PIC 18Fxx2 Architecture
It is suspected that the favorite
bible story of microprocessor (µP)
architects is “The Tower of Babel”
given the gazillion varieties of
microcontrollers available, each
with its unique set of instructions,
registers, and features. But don’t
worry, we will only concentrate on
one in this lab. Unfortunately, it is
generally agreed the first µP
instruction set you learn is the
toughest....
Summary
Use MPLAB to assemble and execute a small assembly language program. Execute the same program on a
PIC18Fxx2 model in Maxplus-II, and trace data movement on internal data busses.
2—1
Experiment 2: The PIC 18Fxx2 Architecture
Summer 2004/V0.2
A. PreLab Requirements
Table 2–1: Prelab Checkoff
Do This
1.
2.
Comments
Attached to this lab is a program called
mptst.asm. Assemble and execute this program in MPLAB using the 18F242 as the target device. Follow the instructions below on
how to do this.
Trace the program until address
0x0212 in program memory is
reached.
Change the value of the myid symbol to be
the decimal equivalent of the last two digits
of your student id. If the last two digits of
your student ID are ‘00’, then use the first
two digits.
Verify that the value of the ‘k’ variable stored at location ‘0x02’ has the
expected value in it given the new
value of myid.
Verify that the value of the k variable
stored at location 0x02 has the value
0xC9 at this point.
Trace the program until address 0x0212 in
program memory is reached. Capture a
screen shot that shows the ‘Program memory’ and ‘File Register’ contents at this point.
A quick introduction to
MPLAB
If you have not already done so, install the latest version of MPLAB on your PC by visiting to http://
www.microchip.com, selecting ‘Engineer’s Toolbox
→Development Tools →Software →MPLAB IDE’,
and downloading the MPLAB IDE executable.
Copy the file mptst.asm to a local directory. Caution:
MPLAB 6.0+ does not allow pathnames to exceed 62
characters so be careful where you place this file. Execute MPLAB and create a new project for it. Call the
new project mptst and browse to the directory that contains mptst.asm. Use ‘View →Project’ to view the
project file hierarchy. Right click on ‘Source Files’
2—2
Summer 2004/V0.2
Experiment 2: The PIC 18Fxx2 Architecture
and use the ‘Add Files...’ command to add mptst.asm
to the project.
At this point the project window should appear as
shown on the right.
Use ‘Project Set Language Toolsuite’ and choose
‘Microchip MPASM Toolsuite’. This selects the tools
used to assemble or compile files in the project.
Next, use ‘Configure →Select Device’ and select the
PIC18F242 as the target device. Before doing any
editing of the program, use ‘Project →Build All’ to
assemble the program, which should produce a “Build
Succeeded” message in the output window.
Use ‘Debugger →Select Tool →MPLAB Sim’ to set
the MPLAB simulator as the debugging tool. Use
‘View Program Memory’ to view the machine code of
your program (use the Symbolic button the program
memory window to see the most readable representation of the code). Use ‘View File Registers’ to view
the internal memory of the PIC. Use ‘View Special
Registers’ to view the special registers (W, TRISA,
Simulating your program
2—3
Experiment 2: The PIC 18Fxx2 Architecture
Summer 2004/V0.2
PORTA, etc.) of the PIC. Double click on the
mptst.asm file in the project window to open a source
file window. Use either F6 or ‘Debugger →Reset
→Processor Reset’ to reset the processor’s program
counter to point at the instruction in location 0. The
figure below is approximately what should be displayed:
Single Stepping
2—4
Use F7 or ‘Debugger Step Into’ to single step through
the program. The Special Function Registers window
is useful for observing changes to often-used registers
such as W and STATUS. The File Registers window is
useful for observing changes to all of the other internal
memory locations of the PIC.
Summer 2004/V0.2
Experiment 2: The PIC 18Fxx2 Architecture
In this program, using the original value of 100 for the
myid definition causes the k variable to finish with the
value 201 (0xC9). Single step the program until location 9 is reached and verify that location 0x02 (corresponds to variable k) has the value 0xC9.
To start the program back at location “0x0”, use
“Debugger →Reset Processor →Reset” (bound to the
F6 key). To clear data memory contents back to their
original values, select “Debugger →Clear Memory
→GPRs”. The command “Debugger →Clear Memory
→All Memory” clears all memory including program
memory requiring the file to be re-assembled before
execution.
Reset, Clearing Memory
A project does not have to be created each time you
want to assembly and simulate a file. Close MPLAB,
then re-open it, and open the mptst.asm file. Next, use
‘Configure →Select Device’ and select the
PIC18F242 as the target device. Now use ‘Project→Quickbuild mptest.asm’ to assemble the program without creating a project. If you only have one
file to assemble, use QuickBuild instead of building a
project.
QuickBuild Mode instead
of Projects
The command “View →Watch” opens a watch window which is useful for monitoring select memory
locations. After the watch window is opened, use the
pull down list next to the Add Symbol button to list all
variables in the program. Find the i symbol, then click
Add Symbol to add it to the watch window. Do the
same for the j, k variables. You are now able to monitor these values during program execution.
Watch Window
Use the command “Debugger →Animate” to watch
the program execute in slow speed. Use the F5 key
(halt) to stop execution.
Animate Command
2—5
Experiment 2: The PIC 18Fxx2 Architecture
Summer 2004/V0.2
B. Lab Activity
Exploring PIC18 Data
memory organization
This part of the lab explores how the data memory of
the PIC18 is organized.
Table 2–2: Data Memory variations checkoff
Activity
Questions to be answered
1.
Modify the mptst.asm file so that the
CBLOCK starting location is now 0x80.
Re-assemble and re-execute the program. Verify that the i, j, k variables are
updated at locations 0x80-0x82.
When the program memory is viewed, the
instruction at program location 0x202 is
now different from the original mptst.asm
file. Record this difference, and determine
the reason for this behavior.
2.
Modify the mptst.asm file so that the
CBLOCK starting location is now 0x100.
Re-assemble and re-execute the program.
Use the File Registers window to determine what locations are changed when
the i, j, k variables are modified. Record
these locations and determine the reason
for this behavior. Hint: look at the definition of the BSR (Bank Select Register).
3.
To the program in step 2, add the statement “MOVLB 0x1” just after the ‘main’
label and before the statement ‘movlw
myid’. Re-assemble and re-execute the
program. The “MOVLB” instruction is
“Move Literal to Bank Select Register”;
“MOVLB 0x1” moves the value 0x1 to the
BSR (BSR= Bank Select Register).
Use the File Registers window to determine what locations are changed when
the i, j, k variables are modified. Record
these locations and determine the reason
for this behavior.
4.
Based on the knowledge gained from
steps 2 and 3, modify the mptst.asm program so that the i,,j,k variables are
located at locations 0x200-0x202. Reassemble, re-execute, and verify that
these locations are modified.
Data Memory Banks in
the PIC18
2—6
The data memory banks in the PIC18 is split into multiple banks. The PIC18F242 has three banks - bank0
(0x00-0xFF), bank1 (0x100-0x1FF), and bank2
(0x200-0x2FF). A 8-bit memory address within a
PIC18 instruction word specifies the location within a
bank; the value in the Bank Select Register (BSR)
selects the bank that is accessed. The default value for
the BSR is 0, which means that Bank 0 is selected by
Summer 2004/V0.2
Experiment 2: The PIC 18Fxx2 Architecture
default. To select Bank 1, the value 0x1 must be placed
in the BSR. This can be done by executing the instruction:
MOVLB 0x1
which moves the value 0x1 into the BSR, selecting
bank 1. To select Bank 2, one can do:
MOVLB 0x2
which moves the value 0x2 into BSR, selecting Bank
2. To reselect Bank 0, do:
MOVLB 0x0
When specifying an address in a PIC18 instruction, if
the ‘access’ bit is set, then the BSR register is ignored,
and addresses 0x00-0x7F are mapped to locations
0x00-0x7F in bank 0 (access bank low), and addresses
0x80-FF are mapped to locations 0xF80-0xFFF
(access bank high) which are the special function registers (WREG, STATUS, etc.). The ‘movf’ instruction
below forces the address for j to be in the access bank.
movf j,w,A
;ignore BSR register
The ‘movf’ instruction below uses the BSR with the
address of j:
movf j,w,BANKED ; use BSR register
With MPLAB, you should not have to use either the
‘A’ (use access bank) or ‘BANKED’ (use BSR) qualifiers on instructions as long as the CBLOCK statements have the full bank address for a variable (i.e,
address 0x100 for ‘j’ places j in bank 1) as the default
rules for variable access in the absence of ‘A’ or
‘BANKED’ make sense. If you do not explicitly specify the ‘A’ or ‘BANKED’ qualifier on an instruction,
the following rules are used by MPLAB assembler:
2—7
Experiment 2: The PIC 18Fxx2 Architecture
Summer 2004/V0.2
a. If the address for the variable is between 0x0 - 0x7F,
or between 0xF80-0xFF (special function registers),
then qualifier ‘A’ is assumed, which causes the BSR to
be ignored, forcing it into bank 0.
b. If the address is between 0x80 and 0xF7F, then
qualifier ‘BANKED’ is assumed, which causes the
BSR to be used for data access.
SHOW THE TA THE RESULTS FOR STEPS 1-4 AND
EXPLAIN THE REASONS BEHIND THE OBSERVED
RESULTS.
BE SURE TO INCLUDE THIS REASONING IN
THE LAB REPORT.
2—8
Summer 2004/V0.2
Experiment 2: The PIC 18Fxx2 Architecture
This portion of the lab explores moving data between
memory banks.
Moving data between
banks
.
Table 2–3: Data Movement Checkoff
Activity
Questions to be answered
1.
In MPLAB, open a “File Registers” window that shows locations 0x0000 through
0x0120. Click on the first line of ‘...’ under
the ASCII column and type the first 5 letters of your first name, and seven digits of
your phone number. Then type enough
spaces so that the entire type in column
has been filled.
Record what appears in the hex locations
0x0 through 0x0F. Justify to yourself the
reason for these values (and explain in
the lab report).
2.
Using the mptst.asm file as a starting
point, create a new program with a series
of data movement instructions that will
move the contents of locations 0x0-0x7 to
locations 0x100 -0x107. Verify the operation of this program by typing data of your
choice into locations 0x0-0x7, executing
your program, and verifying that the data
is moved to locations 0x100-0x107. You
may NOT use the ‘movff’ instruction in this
program.
You do not need a CBLOCK statement for
this program, you can specify addresses
for memory locations within instructions
as:
Create a new version of the program done
in step 2 (keep the old version!) that uses
the ‘movff’ instruction to accomplish the
data movement (i.e., ‘movff 0x0, 0x100’
moves the contents of location 0x0 to
0x100). Re-assemble, and verify that your
program exhibits the same behavior as
the program in step 2.
Starting at location 0x200 in Program
Memory, determine the number of BYTES
needed for this program (most PIC18
instructions need 2 bytes, some need 4
bytes). Report this number IN DECIMAL.
3.
movf 0x0, w
You may find the instructions “BSF BSR,
0” (bit set) and “BCF BSR, 0” (bit clear)
useful.
Starting at location 0x200 in Program
Memory, determine the number of BYTES
needed for this program (most PIC18
instructions need 2 bytes, some need 4
bytes). Report this number IN DECIMAL.
Which program took fewer program
bytes?
DEMO THE PROGRAMS YOU WROTE IN STEPS 2 AND 3
TO THE TA.
2—9
Experiment 2: The PIC 18Fxx2 Architecture
Summer 2004/V0.2
showid.asm
The showid.asm program attached to this lab duplicates the action of the Student ID CPU of the previous
lab by copying the even or odd digit sequence of a student ID to the out variable. The odd input is simulated
through a variable called odd; if the least significant
bit (LSB) of variable odd is 0 then the even sequence
is chosen, else the odd sequence is chosen. Variable
odd is located at location 0x0 in data memory; this
value can be changed by opening a File Registers window and directly typing a new value in location 0x0.
bit test and skip
The LSB of variable odd is tested via the instruction
sequence:
btfsc odd, 0
goto odd_seq
The btfsc instruction tests if a particular bit of the specified file register is clear (a logic 0 value). If the specified bit is clear, then the next instruction is skipped. In
this case, the next instruction is a jump to the sequence
of instructions the copies the odd sequence to the out
variable.
Controlling the value of
odd
Note that the variable odd is cleared to 0x00 by the
instruction ‘clrf odd’. This causes the even
sequence to always be chosen. To cause the odd
sequence to be chosen after reset, replace the instruction ‘clrf odd’ with ‘bsf odd, 0’. This sets the
LSB of file register odd to a logic 1. During program
execution, you can type a new value for odd into the
location 0x0 in the file registers window to change the
number sequence that is displayed.
The Stopwatch
The command “Debugger →Stopwatch” can be used
to display how many instruction cycles and how much
time an instruction requires when executed. This is
useful in determining the amount of execution time
required for a particular section of code. The com-
2 — 10
Summer 2004/V0.2
Experiment 2: The PIC 18Fxx2 Architecture
mand “Debugger →Settings” can be used to changed
the simulated clock frequency of the processor.
Table 2–4: showid Checkoff
Checkpoint
Comments
1.
Single step through showid.asm in
MPLAB for both odd and even
sequences. Note that location 0x0 corresponds to out, and 0x01 to odd.
To force the odd sequence, either do as
above and modify the instruction that initializes odd, or directly change variable
odd (location 0x20) by typing into the file
register window.
2.
Modify showid.asm to display the digits
of your student id. Assemble and verify
the operation.
3.
Use the ‘Stopwatch’ command in the
simulator and record the instruction
cycles and time for displaying all of the
odd digits of your student ID.
This instruction count and time is for one
complete pass through the loop. Use a
time of 20 MHz and record this time.
Then change the clock speed to 8 MHz
and record this time.
4.
Use the ‘Stopwatch’ command in the
simulator and record the instruction
cycles and time for displaying all of the
even digits of your student ID.
This instruction count and time is for one
complete pass through the loop. Use a
time of 20 MHz and record this time.
Then change the clock speed to 8 MHz
and record this time.
DEMO THE SHOWID PROGRAM THAT DISPLAYS THE
DIGITS OF YOUR STUDENT ID TO THE TA.
The showid.asm program does a poor job of emulating
the student ID CPU as the variables odd and out are
internal memory locations and do not correspond to
external pins on the PIC18Fxx2. However, you will
soon discover that setting and testing external pin values is done in the same way as internal memory locations.
A poor emulation?
2 — 11
Experiment 2: The PIC 18Fxx2 Architecture
Summer 2004/V0.2
C. Report
1. Include the ‘.lst’ files of any assembly language
programs written for this lab.
2. Include the MPLAB screenshot required in the
prelab checkoff.
3. Include the results from Table 2–2 and your reasons for the observed behavior.
4. Include the results from Table 2–3 and your reasons for the observed behavior.
5. Include the results from Table 2–4 and verify via
manual calculations that the recorded time for both
even and odd sequences is correct, for both clock
frequencies. Explain the execution time required
for the ‘btfsc odd,0’ under both conditions (odd = 0
and odd = 1).
6. For the following instruction, assume j is location
0x64 and has an initial value of 0x40. Give the values of w and j after the instruction is executed as
well as the machine code for the instruction:
decf j, w
7. For the following instruction, assume j is location
0x7C and has an initial value of 0xDA. Give the
values of w and j after the instruction is executed as
well as the machine code for the instruction:
incf j, f
2 — 12
Summer 2004/V0.2
E x p e r i m e n t
Experiment 3: PIC18Fxx2: Instruction Set
3
PIC18Fxx2: Instruction Set
Surely you’ve seen the TV commercial of the two female engineers
mud-wrestling while arguing about
the PIC instruction set1. “Less Filling!” “Tastes Great!”. Well, I’m not
sure about tastes great, but less
filling is right on. So much so, you
often find yourself saying ‘Why in
the #$!*& doesn’t it have instruction X?!?’ But, fewer instructions
means less to know! Woot!
Summary
Experiment with different PIC instruction sequences
in the context of C code examples.
1. At least, I think that’s what the argument is about. They never really
say.....
3—1
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
A. Prelab Requirements
Table 3–1: Prelab Checkoff
Do This
1.
Comments
The C programs ops_var{1-5}.c and
loops_var{1-5}.c attached to this lab perform operations on three unsigned byte
variables: i, j, k. Verify that you can compile and execute these programs on any
machine/operating system of your choice.
The programs variants 1 through 5 rearrange C statements in different orders.
For the ‘ops’ programs, the files ‘ops_{al}.c’ define 12 different C operations that
are included in different orders within
ops_var{1-5}.c. For the ‘loops’ programs,
the files ‘loops_{a-e}.c’ define 5 different C
code segments that are included in different orders within loops_var{1-5}.c.
These programs are used to illustrate how
common C operations are implemented in
PIC18F242 assembly language.
These programs can be compiled and
executed on the ECE Unix machine
(leto.ece) once the ZIP archives have
been unpacked into a common directory.
An example compilation/execution is
shown below:
To compile: gcc -o ops_var1 ops_var1.c
This produces the executable ops_var1
To execute: ./ops_var1
Print statements are included after each
block of code to track variable modifications.
2.
Compile and execute your assigned op
and loop program variation as given by
the tables below. Have a printout the values of i, j, k ready for checkoff.
Understand the functionality of your
assigned op/loop program as you are
required to implement these in PIC
18F242 assembly language.
Table 3–2: Program Variations for ‘ops’
If the last digit
of your student
ID is...
3—2
Use the program...
0 or 2
ops_var1.c
1 or 3
ops_var2.c
4 or 6
ops_var3.c
5 or 7
ops_var4.c
8 or 9
ops_var5.c
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
Table 3–3: Program Variations for ‘loops’
If the last digit
of your student
ID is...
Use the program...
0 or 9
loops_var1.c
1 or 8
loops_var2.c
2 or 7
loops_var3.c
3 or 6
loops_var4.c
4 or 5
loops_var5.c
In case you are a bit rusty on C (or have never had it!),
here is a quick review. The use of C in this course is
very simplistic; please refer to any C reference manual
for deeper coverage of the topics presented here.
A Quick C Review
Variables declared as:
unsigned char i, j, k;
are 8-bit (byte) variables. The unsigned modifier is
important as this affects how comparisons such as ‘>’
or ‘<‘ are performed; these variables are compared as
unsigned values. Furthermore, the unsigned modifier
causes a ‘0’ to be shifted into the most significant bit
for a right shift (i >> 1); the MSB stays the same for a
right shift of a signed data type.
The table below explains the operators used in
ops_var{1-5}.c.
Table 3–4: Some C operators
Operator
Comment
++, --
increment (i++) or decrement (i--) the variable by one.
+, -
addition, subtraction
3—3
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
Table 3–4: Some C operators
Operator
Comment
>>, <<
right shift (i >> 1) or left shift (i << 1) a variable by the specified amount.
For unsigned types, a right shift away shifts in a ‘0’ into the MSB. For
signed types, a right shift leaves the MSB bit (sign bit) unchanged. For
left shifts, a ‘0’ is always shifted into the LSB regardless of whether it is a
signed or unsigned type.
|, &, ^
bitwise OR (|), bitwise AND (&), bitwise XOR (^). A bitwise operation
does the specified logic operation with each bit of the two operands.
~
Bitwise negation or complement operation
!
Logical negation (i.e,!j); returns a ‘1’ if the operand is zero; returns a ‘0’ if
the operand is non-zero.
==,!=
Test for equality (i.e, i == j) returns a ‘1’ if i is equal to j, else returns ‘0’.
The test for inequality (i.e, i != j) returns a ‘1’ if i is not equal to j, returns
a ‘0’ otherwise.
>, <, >=, <=
Inequality tests of less than (<), greater than (>), greater than or equal
(>=), less than or equal (<=).
The bitset and bitclr macros in ops_var{1-5}.c use logical and shift operations to do a set or clear on the
specified bit of the operation. The bittst macro returns
the value of the specified bit in the operand; either ‘0’
or ‘1’.
Loops and Conditions
A condition test in C is considered false if the condition test returns a ‘0’ value; true if it returns a non-zero
value. Thus an if statement written as:
if (bittst(i,0)){
/* true block */
} else {
/* false block */
}
will execute the true block if the LSB of variable i is a
‘1’, else it will execute the false block.
The for loop has three parts; initialization, condition
test, and end-of-loop statements:
3—4
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
for (init; ctest; end-of-loop) {
/* loop body */
}
A for statement is equivalent to a while statement written as:
init;
while (ctest) {
/* loop body */
end-of-loop statements
}
The most common use of a for loop is to execute some
block of code a fixed number of times:
for (i=0; i < 10; i++) {
/* loop body */
}
The above code executes the loop body 10 times. The
equivalent while statement is:
i = 0;
while (i < 10) {
/* loop body */
i++;
}
The difference between a while loop and a do-while
loop is that the loop body in a do-while loop is guaranteed to execute at least once because the condition test
is done after the loop body. The above for loop can
also be written as:
for (i=0; i!= 10; i++) {
/* loop body */
}
Note that the bodies of both for loops execute 10
times.
3—5
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
B. Lab Activity
Table 3–5: ops in PIC18F242 Assembly
Checkpoint
1.
Comments/Debugging
Convert your assigned ops_var{1-5}.c
program to PIC18F242 assembly and verify that the i, j, k variables have the same
values at each step as with the original C
program.
Use the table below to determine what file
register locations to use for i, j, k.
The print statements in the original C file
cannot be converted; you must track the
progress of the i, j, k variables by observing memory contents.
Test your code for different i, ,j, k initial
values. Use the STOPWATCH and record
the amount of time it takes for this program to execute with a processor frequency of 20 MHz.
Look at the hints below on implementing
these C operations.
Develop your program one operation at a
time. There is no need to advance to the
next operation until the current one produces the correct value. Do not worry
about any code optimization; do it in the
easiest, most straight forward manner.
Modify the C code to have print statements after each operation if you do not
trust your hand computation of the variable values.
Table 3–6: Register file assignment for ops
If the last digit
of your student
ID is...
0 or 1
i: 0x48 (bank 0), j: 0x49 (bank 1), k: 0xC8 (bank 2)
2 or 3
i: 0x51 (bank 2), j: 0x31 (bank 0), k: 0x52 (bank 1)
4 or 5
i: 0xE1 (bank 1), j: 0x60 (bank 2), k: 0x61 (bank 0)
6 or 7
i: 0x70 (bank 0), j:0xB1 (bank 2), k: 0x30 (bank 1)
8 or 9
i: 0xC4 (bank 1), j:0x44 (bank 0), k: 0xC5 (bank 2)
STATUS Register: Carry,
Zero Flags
3—6
Use the following locations...
That STATUS register is a special function register
whose individual bit values are called referred to as
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
flags, and which are set or cleared as a side-effect of
instruction execution. There are two other bits in the
STATUS register that are useful in this exercise. They
are the carry flag (bit 0), and zero flag (bit 2). The
carry (C) flag is affected in multiple ways, but the
most common methods are through addition and subtraction. In an addition, the carry bit is set when there
is a carry out of the MSB. In a subtraction, the carry bit
is cleared if there is a borrow into the MSB during the
subtraction. The carry flag will prove useful in
unsigned comparisons operations. The zero (Z) flag is
set whenever the result of an operation is zero. The
zero flag is useful in equality tests. The C and Z flags
are set as side-effects of PIC operations. Look at the
instruction descriptions to determine when these flags
are affected; not all instructions affect these flags.
Convert each C operation separately from the other,
and use the simulator to check the result as you go.
Remember that the w register is involved in every twooperand PIC instruction. If it is a two-operand calculation such as k = i op j, use the approach:
Converting the C operations to PIC Assembly
1. load the w register with i
2. perform op j; store the result in w
3. store the w register to k.
For example, if the calculation is k = i + j, then:
movf i,w
; w ← i
addwf j,w
; w ← w + j
movwf k,w
; k ← w
This code assumes that i, j, k are all in bank0. If k is in
bank1, the code is written as:
movf i,w
addwf j,w
; w ← i
; w ← w + j
3—7
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
movlb 0x1
; select bank1
movwf k,w
; k ← w
movlb 0x0
; re-select bank 0
If the operation k=k+i, then the code is written as:
movf i,w
; w ← i
movlb 0x1
; select bank1
addwf k,f
; k ← w + k
movlb 0x0
; re-select bank 0
Note that in this case the addwf command is written to
modify the k file register location. This is because k is
both a source operand of the operation, and the destination.
arithmetic operations
The arithmetic operations (addition, subtraction, increment, decrement), are straightforward as there are PIC
instructions that do all of these. Remember that with
the subtraction operation, it is f - w, where f is the file
register value, and not vice-versa. The increment and
decrement operations are convenient in that a separate
instruction does not have to be used to load the w register with the operand value; the instruction does this
automatically.
logical operations
The PIC has instructions for AND, OR, XOR, and
complement (negation) that do the equivalent of the
bitwise operations in C, so conversion is again straight
forward.
Shift operations
The PIC has two rotate instructions (left and right) that
are used to implement shift operations. A rotate right
performs a shift right, with the MSB filled by the value
of the carry bit, and the LSB becoming the new carry
bit. A single shift right (i >> 1, i is an unsigned char)
using a rotate instruction is written as:
bcf STATUS,C
rrcf i,f
3—8
; clear carry
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
Repeat this sequence as many times as needed to
accomplish the specified C shift operation. Do not put
the code in a loop; simply duplicate the two-instruction sequence. In the above code, STATUS and C are
symbols that are defined in the “pic18f242.inc’ file as:
STATUS
EQU
H'0FD8'
C
EQU
H'0000
The previous BCF instruction could have been written
as:
bcf 0xFD8,0
; clear carry
but this is much less readable. Symbols for special
function registers and bits/bit fields within special
function registers are declared in “pic18f242.inc”. Use
these symbols to improve code readability. These symbols are all declared as uppercase, and MPLAB is case
sensitive, so you will get an ‘undeclared symbol error’
for the following code:
bcf status,c
; clear carry
because ‘status’ and ‘c’ are lowercase.
A shift left (i << 1) is done in the same way; clear the
carry flag before executing the rotate instruction:
bcf STATUS,C
; clear carry
rlcf i,f
DEMONSTRATE YOUR OPS.ASM PROGRAM AND
SHOW THAT THE I, J, K RESULT VALUES ARE THE
SAME AS PRODUCED BY THE C CODE. BE PREPARED
TO CHANGE THE INITIAL VALUES OF I, J, K.
3—9
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
Table 3–7: loops in PIC18F242 Assembly
Checkpoint
1.
Comments/Debugging
Convert your assigned loops_var{15} program to PIC18F242 assembly
and verify that the i, j, k variables
end up with the same values as your
original C program.
Use the same variable location
assignments as used for the ops
program.
Look at the hints below on implementing loops and condition checks
in PIC assembly language.
Again, convert one block at a time
and verify the result before proceeding to the next block.
Test your code for different i, ,j, k initial values.
Condition Tests
A condition test is part of all loops and if statements.
The four types of condition tests used in this lab are:
1.
2.
3.
4.
Test for bit set or clear
test for a particular bit being zero or non-zero
test if an entire byte is zero or non-zero
test if a byte is less than or greater than a value
test if a byte is equal to another value
An condition check for a particular bit set or clear is
easy because the PIC has direct instructions for this.
The C code:
if (bittst(i,5)) {
/* true block */
} else {
/* false block */
}
can be directly translated as:
btfss i, 5
goto false_block
true_block
3 — 10
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
...true blk
goto false_block_end
false_block
...false blk
false_block_end
... remaining statements
Note that the ‘bit test and skip if set’ (btfss) instruction
is used because the condition is checking for the bit
being equal to a ‘1’.
The condition below:
if (i) {
/* if_body */
}
executes the if body if i is nonzero. This can be implemented as:
movf i,f
;move i onto itself!
btsfc STATUS, Z
goto skip
; Z=1, so i == 0
...if body...
skip
... rest of code
Note that the movf i,f instruction moves i onto itself;
the only useful thing this accomplishes is setting the Z
flag if i is zero. The if body true is executed if i is nonzero.
The condition below:
if (!i) {
Zero/Nonzero Test with
branch instruction
/* if_body */
}
executes the if body if i zero. This could be implemented using the ‘movf/btsfsc’ approach above, or can
be done by PIC18 code:
3 — 11
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
tstfsz i
; is i == 0?
goto skip
; i != 0, skip
...if body... i is zero
skip
... rest of code
The tstfsz instruction is ‘test F, skip if zero’; it skips the
next instruction if the file register contents is zero.
There is usually more than one way to accomplish a
task, use the approach that you understand the best.
Zero/Nonzero Test with
branch instructions
The condition below:
if (i) {
/* if_body */
}
can be implemented using the branch instructions,
which are conditional goto instructions based upon the
setting of a single flag bit in the status register:
movf i,f
bz skip
;move i onto itself!
; skip if Z=1
...if body...
skip
... rest of code
The ‘bz skip’ (branch on zero) instruction jumps to
skip (branches to skip) if Z = 1.
The condition below:
if (!i) {
/* if_body */
}
can be written as:
3 — 12
movf i,f
;move i onto itself!
bnz skip
; skip if Z=0
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
...if body...
skip
... rest of code
Using branches typically improves code clarity and
reduces instruction count. The remaining code examples use branches to implement condition tests.
To perform a test such as A > B, note that this is the
same as A - B > 0. This test is true if the result is nonzero (Z = 0) and if no borrow occurred during the subtraction (C = 1). Written in a boolean fashion:
<, > tests
(A-B > 0) is true if (!Z) & C
(A-B > 0) is false if Z |!C
The false test is derived by using DeMorgan’s law on
the true test. The statement below:
if (i > j) {
/* if body */
}
can be to translated to PIC assembly as:
movf j,w
;w ← j
subwf
; w ← i - w
i,w
bz skip
; skip if Z=1
bnc skip
; skip if C=0
; Z=0 & C=1, do if body
..if body....
skip
... rest of code...
The subtraction operation is written to leave the operands unchanged; its only purpose is to affect the flags.
Note that the if body is executed if the two successive
bit operations are both true (the AND condition, as in
‘!Z & C’). The if body is not executed if either bit test
fails (the OR condition, as in ‘Z | !C’).
3 — 13
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
The test for i > j is accomplished in fewer statements if
the subtraction j - i is performed instead of i - j. If i is
greater than j, then j - i will produce a borrow (C = 0).
Thus, the PIC assembly is written as:
movf i,w
;w ← i
subwf
; w ← j - i
j,w
bc skip
;skip if C=1
; C=0, do if body
...if body....
skip
... rest of code...
To implement
if (i >= j) {
/* if body */
}
the subtraction i-j will not produce a borrow (C=1) if
the comparison i >= j is true. This is implemented as:
movf j,w
;w ← j
subwf
; w ← i - j
i,w
bnc skip
;skip if C=0
; C=1, do if body
...if body....
skip
... rest of code..
The table below shows the subtraction operation and C
flag test required for the comparison i > j and i >= j
which is sufficient for all comparisons (i < j can be
written as j > i, and i <= j is j >= i).
3 — 14
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
Unsigned Comparison
Operation
Flag setting if true
Flag setting if false
i>j
j-i
C = 0 (borrow occurred)
C=1 (no borrow)
i >= j
i-j
C = 1 (no borrow)
C=0 (borrow occurred)
An alternate method of accomplishing:
Compare instructions
if (i > j) {
/* if body */
}
is to use the cpfsgt instruction (Compare F with W,
skip if >). This instruction combines the ‘subwf’ and
‘btfsc’ of the previous example into one instruction.
Thus, the PIC18 assembly is written as:
movf j,w
;w ← j
cpfsgt
; i > j?
i
goto skip
;skip if i =< j
; i > j, do if body
...true block....
skip
..rest of code...
The instruction cpfslt instruction (Compare F with W,
skip if <) can be used for the i < j compare operation.
The >= (greater than or equal) test:
if (i >= j) {
/* if body */
}
can be written as:
3 — 15
Experiment 3: PIC18Fxx2: Instruction Set
Summer 2004/V0.2
if (! (j > i)) {
/* if body */
}
which reads “if NOT ( j > i) ”. One way to implement
the above test in PIC18 assembly is:
movf i,w
cpfsgt
j
;w ← i
; j > i?
goto if_body
;i >= j
goto skip
;j > i
if_body
.... if body code....
skip
..rest of code...
WARNING: While the compare instructions can
result in fewer instructions, they cannot be used for
16-bit inequality comparisons. The subtraction/flag
test approach is the more general approach and you
need to understand it as we will be using that approach
for other types of comparisons in future labs.
Equality, Inequality tests
Equality (i == j) and inequality (i != j) are done in a
similar manner using the subtraction operation. Equality is true if Z=1 after the i-j operation; inequality is
true if Z=0 after the i-j operation. The cpfseq instruction (compare F, skip if equal) can also be used if
desired.
DEMONSTRATE YOUR LOOPS.ASM PROGRAM AND
SHOW THAT THE I, J, K RESULT VALUES ARE THE
SAME AS PRODUCED BY THE C CODE. BE PREPARED
TO CHANGE THE INITIAL VALUES OF I, J, K.
3 — 16
Summer 2004/V0.2
Experiment 3: PIC18Fxx2: Instruction Set
C. Report
1. Include the lst files for all assembly language programs and any C source code. Comment your
assembly language program very well; at least one
comment every other line (points will be deducted
if your assembly program is not well commented).
2. For the ops program, calculate the total number of
8-bit operations performed (each 8-bit assignment
counts as 1, each logical/add/sub/inc/dec counts as
1, each shift operation counts as 1). For shift operations, count each required shift as 1 (a >> 3 counts
as 3 shift operations). Make this calculation based
on the C code, not the assembly code. Take the execution time value recorded for the ops program,
and divide by the total number of 8-bit operations
to get an average execution time per 8-bit operation. Take the inverse of this value to get the number 8-bit operations per second that can be
expected from the PIC18 running at 20 MHz. Compare this to what is obtained by taking the ADDWF
instruction and computing the same values based
on its execution time. Why are the values different?
Discuss this in your report. What could be done differently in the ops program to give it higher performance?
3 — 17
Experiment 3: PIC18Fxx2: Instruction Set
3 — 18
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 4: Data: Wider is Better
4
Data: Wider is Better
µP life crawled out upon the silicon
beach in 1972 as a 4-bit critter,
then began expanding faster than a
Japanese rubber-suit monster eating nuclear waste -- first 8 bits,
then 16, 32...64...128....Mommie!!!
Will the madness ever stop?!
...Hopefully not, because then us
hardware types would be out of a
job. Can the lil’ ol PIC handle wide
data? Sure! ... Fast?.... Nope! But
many times, getting the job done
slowly is perfectly alright. But don’t
try that with your lab report!
Summary
Experiment with manipulating 16-bit arithmetic operations, and comparisons on 16-bit unsigned and signed
data.
4—1
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
A. Prelab Requirements
Table 4–1: Prelab Checkoff
Do This
1.
Comments
The C programs intops_var{1-5}.c
attached to this lab performs operations
on two unsigned 16-bit integer variables: i,
j. The C programs unsigned_var{1-5}.c
performs operations on two unsigned 16bit variables. The C programs
signed_var{1-5}.c performs operations on
two signed 16-bit variables. Verify that you
can compile and execute your assigned
program versions on any machine/operating system of your choice.
When viewing the printed i, j values from
within signed_var{1-5}.c, ignore the most
significant four ‘F’ digits if 8 hex characters (32-bits) are displayed for a value.
This is the extension of the sign bit to 32bits.
Have a printout of the i, j values for both
programs ready for checkoff.
2.
The following HEX values are 2’s complement, 8-bit integers. Convert to decimal.
a) 0xFD, b)0x70 c) 0x82
3.
Convert the following signed decimal values to 8-bit two’s complement values. Write
the values in Hex.
a) -20 b) -78
4.
c) + 39
Perform the following operations, give the result in hex. Also give the values for the N,
V, C flags based on the 16-bit computation.
a) 0xA8AF + 0x9C23
b) 0x49B0 - 0x82F3
5.
The machine code for a branch instruction is 0xE4E6 and is located at address
0x0232. What branch instruction is this and what is the target address?
6.
What is the machine code for instruction sequence below. Does this machine depend
on where it is located in memory?
here
bra here
4—2
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
Table 4–2: Program variations for ‘intop’
If the last digit
of your student
ID is...
Use the program...
0 or 3
intop_var1.c
1 or 4
intop_var2.c
2 or 5
intop_var3.c
6 or 9
intop_var4.c
7 or 8
intop_var5.c
Table 4–3: Program variations for ‘unsigned’, ‘signed’
If the last digit
of your student
ID is...
Use the programs...
0 or 1
unsigned_var1.c, signed_var1.c
2 or 3
unsigned_var2.c, signed_var2.c
4 or 5
unsigned_var3.c, signed_var3.c
6 or 7
unsigned_var4.c, signed_var4.c
8 or 9
unsigned_var5.c, signed_var5.c
The char data type is always 8 bits regardless of the
processor type. The size of the int data type is dependent upon the processor and is typically 32 bits. A
short int is 16 bits. A long data type on high performance CPUs is 64 bits; on most other CPUs it is 32
bits. The following program can be used to determine
the data sizes of a particular C implementation:
Data Sizes in C
main()
{
printf (" A char is %d bits.\n", sizeof(char)*8);
printf (" A short int is %d bits.\n", sizeof(short int)*8);
printf (" A int is %d bits.\n", sizeof(int)*8);
printf (" A long is %d bits.\n", sizeof(long)*8);
4—3
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
}
By default, a char, int, or long type is assumed signed
unless specified otherwise via the unsigned modifier.
4—4
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
B. Lab Activity
Table 4–4: intops.c in PIC16F873 Assembly
Checkpoint
1.
Comments/Debugging
Convert your assigned intops_var{1-5}.c
program to PIC18F242 assembly and verify that the i, j variables finish with the
same values as your original C program.
Use the table below to determine what file
register locations to use for i, j.
Test your code for different i and j initial
values.
Use the STOPWATCH and record the
amount of time it takes for this program to
execute with a processor frequency of 20
MHz.
Look at the hints below on implementing
these C operations.
Develop your program one operation at a
time. There is no need to proceed to the
next operation until the current one produces the correct value. Do not worry
about any code optimization; do it in the
easiest, most straight forward manner.
Modify the C code to have print statements after each operation if you do not
trust your hand computation of the variable results.
Table 4–5: Register file assignment for intops.c
If the last digit
of your student
ID is...
Use these locations...
0 or 9
i: 0x53 (bank 0), j: 0x55 (bank 0)
1 or 8
i: 0x5A (bank 0), j: 0x5E (bank 0)
2 or 7
i: 0x63 (bank 0), j: 0x68 (bank 0)
3 or 6
i: 0x71 (bank 0), j: 0x77 (bank 0)
4 or 5
i: 0x4A (bank 0), j: 0x4C (bank 0)
When storing an integer that is more than one byte in
memory, the bytes can arranged either least significant
to most significant (little endian) or most significant to
least significant (big endian). On an 8-bit processor
like the PIC, the choice is up to the programmer. There
is no inherent advantage to either ordering. As an
example, the code below uses little endian format for
Storing 16-Bit values in
memory
4—5
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
the 16-bit variable i that is initialized to the value
0xC428:
CBLOCK 0x040
i_low, i_high
ENDC
org 0
movlw 0x28
movwf i_low ; LSB = 0x28
movlw 0xc4
movwf i_high
;MSB = 0xC4
The low and high bytes are explicitly named i_low and
i_high for clarity, with i_low at location 0x40 and
i_high at location 0x41. Another way to accomplish
the same thing is shown below:
CBLOCK 0x040
i:2
ENDC
org 0
movlw 0x28
movwf i
; LSB = 0x28
movlw 0xc4
movwf i+1
;MSB = 0xC4
In this example, the statement i:2 reserves two bytes of
storage for i. The Least Significant Byte (LSB) is referenced as i, while the Most Significant Byte (MSB) is
referenced as i+1 as it resides in the byte location following the LSB. In these examples, little endian byte
ordering will always be used.
4—6
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
Assume that the 16-bit variables i, j are declared as
shown below:
Addition/Subtraction of
16-bit values
CBLOCK 0x040
i:2, j:2
ENDC
The operation i= i+j can be accomplished via:
movf
j,w
addwf i,f
movf
; w ← j (LSB)
;i LSB ← i LSB + w
j+1,w ; w ← j (MSB)
addwfc i+1,f ;i MSB← i MSB + w +C
The addwfc instruction adds the C (Carry) flag to the
sum of the two MSBs; if a carry is produced by the
addition of the two LSBs then C=1 and this adds a +1
to the MSB sum.
Similarly, in an i=i-j operation, the MSB subtraction is
performed by the subwfb instruction the subtracts from
W with a borrow. This subtracts a 1 from the MSB
subtraction if the subtraction of the two LSBs produces a borrow.
movf
j,w
subwf i,f
movf
; w ← j (LSB)
;i LSB ← i LSB - w
j+1,w ; w ← j (MSB)
subwfb i+1,f ;i MSB← i MSB - w -(~C)
Increment and decrement also can also use the addwfc/
subwfb instructions. One way to do an integer increment (i++) is:
movlw 0x00
incf i,f
increment, decrement
; w ← 0
;i LSB ← i LSB + 1
addwfc i+1,f ;i MSB← i MSB + 0 +C
4—7
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
The ‘movlw 0x00’ instruction is needed to ensure that
W is zero for the addwfc instruction used on the MSB.
The following is a more efficient 16-bit increment:
infsnz i,f
;i LSB ← i LSB + 1
incf
;i MSB← i MSB + 1
i+1,f
The infsnz instruction is “increment, skip if nonzero”.
If the result of incrementing the LSB is a zero, then
this means a carry is produced, and the MSB must be
incremented. However, it cannot be generally applied
to values greater than 16-bits.
A 16-bit decrement (i--) can be performed as:
; w ← 0
movlw 0x00
;i LSB ← i LSB - 1
decf i,f
subwfb i+1,f ;i MSB← i MSB -0 - (~C)
or as:
tstfsz i
; is LSB 0?
;i MSB ← i MSB - 1
decf i+1,f
decf i,f
;i LSB← i LSB -1
The second version tests to see if the LSB is zero; if
yes, then MSB is also.
left, right shift
For an unsigned right shift operation, the MSB is
shifted first followed by the LSB, with the carry flag
propagating the carry bit from the MSB to the LSB.
The operation i = i>>1 is written as:
bcf STATUS,C
; clear carry
rrcf i+1, f
; i MSB >> 1
rrcf i, f
; i LSB >> 1
For a left shift operation, the reverse is done; the LSB
is shifted first followed by the MSB.
4—8
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
DEMONSTRATE YOUR INTOPS.ASM PROGRAM AND
SHOW THAT THE I, J RESULTS ARE THE SAME AS PRODUCED BY THE C CODE. BE PREPARED TO CHANGE
THE INITIAL VALUES OF I, J.
4—9
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
Table 4–6: unsigned 16-bit comparisons in PIC18F242 Assembly
Checkpoint
1.
Comments/Debugging
Convert your assigned unsigned_ver{15}.c program to PIC18F242 assembly and
verify that the i, j variables finish with the
same values as the C program.
Use the same file register locations for i, j
as used for the previous section. Use any
address you want for variable k.
Look at the hints below on implementing
signed comparisons in PIC assembly language.
Again, convert one block at a time and
verify the result before proceeding to the
next block.
Test your code for different i and j initial
values.
Unsigned 16-bit comparisons
Unsigned 16-bit comparisons are performed using the
subtraction/C flag test as was done for 8-bit numbers.
The comparison:
unsigned int i, j;
if (i > j) {
/* if body */
}
is accomplished by performing j-i and checking if
C=0. In PIC18 assembly this is:
movf
i,w
subwf j,w
movf
; w ← i (LSB)
; w ← j LSB - i
i+1,w ; w ← i (MSB)
subwfb j+1,w ; w← j MSB -i MSB-(~C)
bc skip
; C = 1, j >= i, so skip
... if _body....
skip
.... rest of code
The cpfsgt or cpfslt instructions cannot be used for 16bit unsigned compares.
4 — 10
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
The equality test below:
16-bit Equality tests
unsigned int i, j;
if (i == j) {
/* if body */
}
is done by performing i-j (or j-i) and checking if both
byte results are zero:
movf
j,w
; w ← j (LSB)
subwf i,w
; w ← i LSB - j
bnz skip
;skip if LSB != 0
j+1,w ; w ← j (MSB)
movf
subwfb i+1,w ; w← i MSB -j MSB-(~C)
bnz skip
;skip if MSB !=0
... if _body....
skip
.... rest of code
The nonzero test below:
16-bit Zero/Nonzero tests
unsigned int i, j;
if (i) {
/* if body */
}
is done by determining if i is non-zero:
; w ← i (LSB)
movf
i,w
bnz
if_body
movf
i+1,w ; w ← 1 (MSB)
bz
skip ;
; if Z=0, i nonzero
if Z=1, then i==0
if_body
... if body code...
skip
4 — 11
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
The above code checks each byte of i to see if it is zero
or non zero. The if body is executed if either byte is
non-zero.
DEMONSTRATE YOUR UNSIGNED PROGRAM AND
SHOW THAT THE I, J RESULTS ARE THE SAME AS PRODUCED BY THE C CODE. BE PREPARED TO CHANGE
THE INITIAL VALUES OF I, J.
Table 4–7: signed 16-bit comparisons in PIC18F242 Assembly
Checkpoint
1.
Comments/Debugging
Convert your assigned signed_ver{1-5}.c
program to PIC18F242 assembly and verify that the i, j variables finish with the
same values as the C program.
Use the same file register locations for i, j
as used for the previous section. Use any
address you want for variable k.
Look at the hints below on implementing
signed comparisons in PIC assembly language.
Again, convert one block at a time and
verify the result before proceeding to the
next block.
Test your code for different i and j initial
values.
Signed Comparisons
4 — 12
Using the same subtraction/C flag test for signed values (2’s complement values) does not work. Table 4–
8 shows the result if unsigned comparisons are used
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
for signed numbers. Note that if both numbers are posTable 4–8: Signed Comparisons for ‘>’
Numbers
As unsigned
i > j?
As signed
i >j?
i = 0x7f,
j = 0x01
i = 127,
j = 01
True
i = +127,
j = +01
True
i = 0x80,
j = 0xFF
i = 128,
j = 256
False
i = -128,
j = -1
False
i = 0x80,
j = 0x7F
i = 128,
j = 127
True
i = -128,
j = +127
False
i = 0x01
j = 0xFF
i = 1,
j = 255
False
i = 1,
j = -1
True
itive or both negative, comparing the numbers as
unsigned numbers gives the same results as signed
comparison. However, if the numbers are different
signs, the wrong answer is produced.
A subtraction approach is used for signed comparisons, but instead of using the C flag, the N and V flags
are tested. The N flag is called the negative flag and is
set when the MSB for a result is ‘1’, indicating the
result is negative for a two’s complement number. The
V flag is called the overflow flag and is set when the
result produces two’s complement overflow. For addition, overflow occurs when the sum of two positive
numbers is negative, or the sum of two negative numbers is positive. For subtraction, overflow occurs when
a negative number subtracted from a positive number
results in a negative number, or when a positive number subtracted from a negative number results in a positive number.
Integer Signed Comparison: N, V flags
4 — 13
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
Assume we want to do the following signed integer
comparison:
signed int i, j;
if (i > j) {
/* if body */
}
If i > j is true, the subtraction j - i should produce a
negative result (N=1, and V = 0). However, if overflow occurs, the result is incorrect, or positive (N = 0,
V = 1).
PIC18 assembly code to accomplish this is:
; for i>j, do j-i
movf i,w
;w= i LSB
subwf j,w
;w= j LSB - i LSB
movf i+1,w
;w= i MSB
subwfb j+1,w
;w= j MSB - i MSB -~C
bn
chk_v
bnov skip
; skip if N=0,V=0
bra if_body
; true if N=0,v=1
chk_v
bov skip
; skip if N=1,V=1
if_body
...if_body....
skip
... rest of code
The above code uses the branch instructions which
cause a jump to the specified label based on the status
of a single bit in the STATUS register. The branch
instructions used above are bn (branch if negative),
bnov (branch if no overflow), bov (branch if overflow). The table below shows the operation required
and flag settings for the comparisons i > j and i >= j.
4 — 14
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
Signed Comparison
Operation
Flag settings if true
Flag settings if false
i >j
j-i
N=1 & V=0
or
N= 0 & V = 1
N=1 & V=1
or
N=0 & V=0
i >= j
i-j
N=0&V=0
or
N=1&V=1
N=0 & V=1
or
N =1 & V = 0
Note that the previous approach for signed int data can
also be used in a simpler form for signed char data by
performing an 8-bit subtraction instead of a 16-bit subtraction.
Equality, zero, and non-zero tests for signed 16-bit
data is performed in the same way as for unsigned
data.
Equality, zero, nonzero
tests for 16-bit signed
data
DEMONSTRATE YOUR UNSIGNED PROGRAM AND
SHOW THAT THE I, J RESULTS ARE THE SAME AS PRODUCED BY THE C CODE. BE PREPARED TO CHANGE
THE INITIAL VALUES OF I, J.
The branch instructions use PC Relative Addressing to
compute the target address for the branch. The
machine code for a branch instruction specifies a word
displacement (1 word = 2 bytes). Let PC be the
address of the branch instruction, and disp be the displacement within the machine code for a branch
instruction. The target address of the branch is computed as:
PC Relative Addressing
Target Address = PC + 2 + disp * 2
The value ‘2’ is added to the PC because the PC will
have been incremented to the next instruction (two
byte locations), and the displacement is multiplied by
two because it is a word displacement (1 word = 2
4 — 15
Experiment 4: Data: Wider is Better
Summer 2004/V0.2
bytes). The Target and PC addresses are byte
addresses.
The displacement can be calculated as:
disp = [Target Address - (PC+1)]/2
The displacement is a 2’s complement number; a negative displacement means the target address is at or
before the branch instruction, while a positive displacement indicates the target address is ahead of the
branch instruction.
4 — 16
Summer 2004/V0.2
Experiment 4: Data: Wider is Better
C. Report
1. Include the lst files for all assembly language programs and any C source code. Comment your
assembly language program very well; at least one
comment every other line (points will be deducted
if your assembly program is not well commented).
2. For the intops program, calculate the total number
of 16-bit operations performed (each 16-bit assignment counts as 1, each logical/add/sub/inc/dec
counts as 1, each shift operation counts as 1). For
shift operations, count each required shift as 1 (a
>> 3 counts as 3 shift operations). Make this calculation based on the C code, not the assembly code.
Take the execution time value recorded for the
intops program, and divide by the total number of
16-bit operations to get an average execution time
per 16-bit operation. Take the inverse of this value
to get the number 16-bit operations per second that
can be expected from the PIC18 running at 20
MHz. Compare this to what is obtained by taking
the ADDWF instruction, computing the same values based on its execution time, and multiplying by
2. Compare these two values, discuss reasons for
any differences.
3. Pick the machine code for either a BOV or BNOV
in your signed program, and show that the displacement value in the machine code is correct given the
PC and target address values.
4. What is missing from the cmpsgt that does prevents
it from being used for 16-bit compares? (HINT,
think about what is needed for a multi-byte compare). What could be changed about its operation to
make it useful for extended compares?
5. Suggest two new branch instructions that could be
added to the PIC18 instruction set that would
improve execution time of signed compares.
Describe the operation of these branches.
4 — 17
Experiment 4: Data: Wider is Better
4 — 18
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 5: Beyond Assembly Language
5
Beyond Assembly Language
By now you have figured out that
programming in assembly language
is just great....if you are a control
freak. You get to specify how each
and every instruction cycle of the
PIC’s existence is spent. However,
this can become.....tedious. So why
learn assembly language? That
answer is easy -- to learn how to
write an efficient C compiler so
that we don’t have to write assembly language any more! Yippee!
Summary
Experiment with indirect addressing and subroutines
in PIC assembly language. Then investigate the
PICC18 compiler for compiling C programs to
PIC18Fxx2 machine code.
5—1
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
A. Prelab Activity
Table 5–1: Prelab Checkoff
Do This
Comments
1.
Read the sections below on pointers
in C and PIC assembly language.
Pointers in PIC assembly language
are also covered in your textbook;
these notes are meant to supplement that material, not replace it.
2.
Read the Lab Activity section and
find the C program that you are
assigned to convert to assembly language. Make a good faith effort at
beginning to implement this in PIC
assembly language and have a listing to show the TA for checkoff.
A ‘good faith effort’ means that the
program is mostly complete and partially debugged. Having one or two
lines of assembly language is not
‘good faith’.
Pointers in C
Pointers in C are convenient as they allow a single reference to a block of data to be passed to a subroutine,
instead of having to copy the block of data itself to the
subroutine. The C code below includes a subroutine
that counts the number of characters in a string. Recall
that strings in C are terminated by a 0x00 (null) value.
char s1[] = "Upper/LOWER.";
unsigned char strcnt (ptr)
unsigned char *ptr;
{
unsigned char i;
i = 0;
while (*ptr != 0) {
ptr++; i++;
}
return(i);
}
5—2
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
main()
{
unsigned char i;
i = strcnt(s1);
}
A pointer contains the memory address of the variable
that the pointer is referencing. In the above code, the
subroutine call strcnt(s1) passes the address of the first
character of s1 to the strcnt subroutine; this address is
stored in the variable ptr, which is a pointer to a char
data type. To read the data that a pointer variable is
referencing, the ‘*’ is placed in front of the pointer
variable. The statement *ptr returns the data value that
ptr is referencing, which in this case is the ASCII
value of the first character of string s1 (a ‘U’ = 0x55).
The statement ptr++ increments the pointer to the
address of the next character in the string. To replace
the value that a pointer is referencing, a statement such
as *ptr = new_value is used. Accessing variables
through pointers is also called indirect addressing.
Two special sets of registers, INDF{0-2} and FSR{02} are used to implement indirect addressing in the
PIC. An FSRn register holds the value of the pointer
itself. An INDFn register is used to access the data that
the pointer is referencing. An implementation of the
strcnt function in PIC assembly language is shown
below.
Pointers in PIC assembly
language
;space for strings in data memory
CBLOCK 0x280 ;put in bank2 for grins
s1:0x10,s2:0x10 ;16 bytes max
ENDC
org
0
goto main
;;
org 0x0200
main
5—3
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
;; copy strings from program memory to
data memory
call init_s1
call init_s2
;; set up call for strcnt
movlw low s1
movwf ptr
movlw high s1
movwf ptr+1
;; ptr = s1 value
call
strcnt ;; do strcnt
;; cnt value is stored in 'i', returned
in 'w'
here
goto here
;parameter, local storage block for
strcnt subroutine
CBLOCK 0x0
i,ptr:2;
ENDC
strcnt
clrf i
;; clear i
movff ptr,FSR0L ;; set FSR low byte
movff
ptr+1,FSR0H ;; set FSR high byte
strcnt_loop
movf
INDF0,w
;; get current char
bz strcnt_exit ;; exit if zero
movwf
0
;;clear w
infsnz FSR0L,f
;; inc FSR0, or ptr++
incf
FSR0H,f
incf
i,f
;; increment char count
bra
strcnt_loop
strcnt_exit
return
Subroutine Parameters
5—4
The strcnt subroutine has one parameter (ptr) and one
local variable (i). In more powerful CPUs that have
more registers and a stack that can be modified under
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
program control, the parameters are passed in registers
or on the stack. However, in the PIC18Fxx2, the lack
of these features means that allocating static space for
parameters is a good solution from a performance and
memory usage point of view. Limitations with this
method are:
1. The subroutine cannot be called recursively (the
subroutine cannot call itself).
2. The subroutine cannot be interrupted, and then
called from the interrupt service routine (interrupts
will be covered in a later lab exercise).
In the example above, the i local variable and the ptr
parameter are allocated in a CBLOCK. In main, the ptr
value is initialized with the address of s1 before the
strcnt subroutine is called. The address of s1 can be
anywhere in the 4K byte data address space, so two
bytes are required for ptr. The assembler directive
‘high s1’ returns the 2nd byte (bits 15-8) of the s1
address; while ‘low s1’ returns the LSB (bits 7-0) of
the s1 address.
main code
In the strcnt subroutine, the FSR0 register is initialized
with the value of ptr, which points to the first character
in the s1 string. The FSR0 register is a 12 bit register
because it points to data memory space, which can be
up 4K bytes.
strcnt subroutine
The instruction
movf INDF0,w
reads the byte referenced by the FSR0 register, places
it in the W register, and affects the Z flag in the process of loading w. This is important, as the end of a
string is marked by a 0x00 value (a null byte). If the Z
flag is set, the subroutine is exited via a return statement, with i containing the number of characters in the
string. If the Z flag is clear, the i variable is incre-
5—5
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
mented to keep track of the number of characters in the
string, and the FSR0 pointer is incremented to point at
the next character in the string via:
infsnz FSR0L,f
incf FSR0H,f
;; inc FSR0,or ptr++
The FSR0L and FSR0H registers refer to the low and
high byte of the FSR0 register, which is 12-bits wide.
You may be tempted to do something like:
incf FSR0,f
This does NOT WORK, as FSR0 is a 12 bit register;
the incf instruction only works on an 8-bit register.
POSTINC0
Incrementing or decrementing FSRn registers are a
common operation. The strcnt assembly code can be
written in a more efficient manner as:
strcnt
clrf i
;; clear i
movff ptr,FSR0L ;; set FSR low byte
movff
ptr+1,FSR0H ;; set FSR high byte
strcnt_loop
movf
INDF0,w
;; get current char
bz strcnt_exit ;; check if zero
movf
POSTINC0,w ;; inc FSR0
incf
i,f
;; increment char count
bra
strcnt_loop
strcnt_exit
return
In the above code, the FSR0 register is incremented by
the instruction:
movf
POSTINC0,w
The above instruction does two operations: it reads the
byte referenced by FSR0 and places it in w, then incre-
5—6
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
ments the FSR0 register. In this case, we do not care
about the character moved into w; incrementing FSR0
is the desired result. Think of POSTINC0 as another
name for INDF0, in which the side effect of using
POSTINC0 is to increment the FSR0 register. The
POSTINC0 register combines ‘*ptr; ptr++’ into one
operation.
Another version of the assembly code for strcnt is
shown below:
strcnt
clrf i
;; clear i
movff ptr,FSR0L ;; set FSR low byte
movff
ptr+1,FSR0H ;; set FSR high byte
strcnt_loop:
movf
POSTINC0,w
;; get current char
;; and increment FSR0
bz strcnt_exit
;; exit if zero
incf
i,f
;; increment char count
bra
strcnt_loop
strcnt_exit
return
Here, the instruction ‘movf INDF0,w’ is replaced by
‘movf POSTINC0,w’; this reads the character and also
increments FSR0 as the same time. This removes the
need to increment FSR0 later in the loop.
Remember that FSRn contains the value of a pointer
(i.e., ptr), and INDFn is used to access what the
pointer is referencing (i.e., *ptr). To increment a
pointer (ptr++), either use the high and low bytes of
the FSRn register (FSRnL, FSRnH) or use the
POSTINCn register. The POSTINCn register references what the pointer is referencing, and increments
the pointer after the reference, so it combines the two
operations ‘*ptr; ptr++’ into one operation.
5—7
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
Other registers similar to POSTINCn are:
PREINCn - does ptr++; *ptr
POSTDECn - does *ptr; ptr--;
PLUSWn - does *(ptr+wreg)
The POSTINCn, PREINCn, POSTDECn are useful
for implementing software stacks or stepping linearly
through data.
The last form, PLUSWn, is useful for implementing C
arrays, where ptr[4] is the same as *(ptr+4).
5—8
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
B. Lab Activity
Table 5–2: Indirect Addressing Task
Checkpoint
1.
Comments/Debugging
Look at the table below, and find the
C program attached to this lab that
you are to implement in PIC assembly language.
Use the strcnt.asm program
attached to the lab as a template for
implementing this code. Use the
init_s1, init_s2 subroutines to copy
the s1, s2 strings from program
memory to data memory.
Each program has a printf statement
in it to illustrate how the s1, s2
strings are affected during execution. Do not implement this statement; use the File Registers window
to determine how the strings are
altered when testing the assembly
code.
In all of these programs, assume
that s1, s2 are the same length and
16 characters or less.
Table 5–3: C Program Assignments
If the last digit
of your student
ID is...
C program, parameter block location
0 or 1
strdcase.c; copies s2 to s1, down cases all letters. Use 0x54 for
the location of the dostr parameter block (ptr1, ptr2).
2 or 3
strflip.c; copies s1 to s2, reversing the case of all letters. Use
0x58 for the location of the dostr parameter block (ptr1, ptr2).
4,5, or 6
strup.c; exchange s1 and s2, up casing all chars in the new s2.
Use 0x5C for the location of the dostr parameter block (ptr1,
ptr2).
7, 8 or 9
strxchg.c; exchange s1 and s2, reversing the case of all chars
in the new s1. Use 0x60 for the location of the dostr parameter
block (ptr1, ptr2).
ASCII data manipulation is used to illustrate indirect
addressing because it is easy to observe the effect of
program execution on the resulting strings. The
amount of ASCII data manipulation a microcontroller
5—9
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
performs is very dependent on the application and can
vary from none to a substantial amount (typically in
the form of a debug monitor that communicates with
an external terminal via a serial link). Indirect addressing is useful for any PIC microcontroller application,
regardless of the amount of ASCII data manipulation
required.
DEMONSTRATE YOUR PIC ASSEMBLY PROGRAM OF
THE ASSIGNED C TASK. BE PREPARED TO CHANGE
THE VALUES OF STRINGS S1, S2.
Table 5–4: C compilation checkoff
Checkpoint
Comments/Debugging
1.
Compile the file cstrcnt.c to PIC18 assembly language following the instructions
below. Simulate the program and single
step it through it to understand the structure of the resulting assembly language.
The file cstrcnt.c must be saved on your
‘unixhome’ drive that is accessible from
the yavin.ece.msstate.edu machine.
2.
Modify the C program assigned in
Table 5–3 so that it can be compiled to
PIC assembly language. Be sure to
remove the printf statement. Complete
Table 5–5 based on the assembly code
produced by C compilation.
The include, define, and __config statements at the top of cstrcnt.c must be
included in a C program for the compilation procedure to succeed.
Simulate the compiled code and verify
that it performs the correct function.
Compiling C programs to
PIC18 machine code
The file cstrcnt.c is a version of strcnt.c that is compatible with the PICC18 C-compiler. The differences
between the two files are:
1. The cstrcnt.c has some includes, defines, and
__config statements before the C code begins. The
defines and __config statements defines PIC startup
5 — 10
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
options needed when the code is programmed into
the PIC.
2. The main program ends in an infinite loop. This is
because there is no place for the main program to
exit to when the code is finished.
3.
To compile cstrcnt.c, save this file to a directory under
your unixhome mounted drive (if you are using your
portable PC, see the class web site for instructions on
how to mount this directory on your PC, which must
be connected to the network via a wireless card or hard
connection).
Use either putty or SSH (secure shell) to open a terminal window to yavin.ece.msstate.edu. This machine
runs Linux, see the class website for a quick UNIX
primer. Once you have logged into yavin, execute the
command: “swsetup hitech”. This places the PIC18
compiler on your executable search path. Change to
the directory (use the ‘cd’ command) that contains
cstrcnt.c - verify that you are in the correct directory
by listing the files in the directory (use the ‘ls’ command).
To compile cstrcnt.c do:
picc18 -O -18F242 cstrcnt.c
The ‘-O’ (capital letter O) is the optimization option; it
instructs the C compiler to optimize the assembly
code. The resulting code will contain fewer bytes and
execute faster than code compiled without this option.
The ‘-18F242’ option designates the target processor;
the 18F242 is the flavor of PIC18 that is used in the
hardware labs.
The output file produced is cstrcnt.hex which is an
ASCII hex representation of the machine code. Execute the command:
5 — 11
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
unix2dos cstrcnt.hex
to convert this file into a format readable by MPLAB.
Import the hex file into MPLAB by doing “‘File →Import”. If the error “end of file has been reached unexpectedly” is displayed, then you forgot to execute the
‘unix2dos’ command.
Another useful compile option is:
picc18 -O -18F242 -Mmap.txt cstrcnt.c
The ‘-Mmap.txt’ option creates a map file called
map.txt. The map file contains a listing of all symbols
in the program and their mapping to memory locations. For example, the symbol _main in the map.txt
file is the location of the entry point for main() in program memory. The symbol _s1 in the map.txt file is
the location of the string s1 in data memory.
The ‘-s’ compile option shown below:
picc18 -O -18F242 -s cstrcnt.c
produces an assembly language source file named
‘cstrcnt.s’ instead of a hex file. This is useful for determining how C language statements are translated to
PIC18 assembly.
Simulating cstrcnt.c
5 — 12
Compile the cstrcnt.c program; produce a map file and
hex file. Use the map file to determine the locations
for the s1, s2 strings in data memory, and the location
of main in program memory. Within MPLAB, import
the cstrcnt.hex file into memory. Use the “Opcode
Hex” button in the program window to see a hex version of the program window; from this you can determine where the s1 and s2 strings are stored in program
memory. Use the “Symbolic” button in the Program
Memory window to see the most readable version of
the disassembled code. Use the simulator and single
step through the first few instructions. Have both the
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
File Registers and Special Function Registers windows open. Use the F8 key to skip over the first two
call instructions (this code is still executed, but the F8
key will cause you to skip over these instructions
instead of single stepping through them). These two
call instructions execute initialization code; the second
call executes code that copies the s1, s2 strings from
program memory to data memory. After executing the
second call, use the File Registers window and determine what memory was modified. Verify that these
data locations match what is specified for the s1, s2
strings in the map file. At this point, follow the program execution through the C code source window
and the assembly code in the Program Memory window.
Modify your assigned C program so that it is compatible with the picc18 compiler. Compile the program
and produce both hex and map files. Use the simulator
to single step through the program and complete the
table below.
Compiling, Simulating
your C program
Table 5–5: Variable, Code Locations
Variable or Code Label
Location (in HEX)
s1 string (in program memory)
s1 string (in data memory)
s2 string (in program memory)
s2 string (in data memory)
main entry point
dostr entry point
ptr1
ptr2
5 — 13
Experiment 5: Beyond Assembly Language
Summer 2004/V0.2
DEMONSTRATE YOUR COMPILED C PROGRAM AND
BE READY TO DISCUSS YOUR VARIABLE AND CODE
LOCATIONS WITH THE
TA.
C. Report
This is a formal lab report; be sure to follow the formatting guidelines posted on the lab web site.
1. Include the lst files for all assembly language programs and any C source code. Comment your
assembly language programs very well; at least one
comment every other line (points will be deducted
if your assembly programs are not well commented).
2. Include the results of Table 5–5 in your report
Formal Report Questions
The following questions refer to the non-PIC microcontroller you are assigned via the lab web site.
3. What is the width of the instruction word?
4. What is the width of the internal data registers?
5. What is the width of the program counter or
instruction pointer?
6. How much on-chip RAM does the processor have?
(RAM = Random Access Memory, memory that
the processor can modify, equivalent to the register
file on the PIC).
7. Can the µP access external memory (memory that
does not reside on the same chip). If ‘yes’, what is
the maximum amount?
8. Does the µP have special instructions for signed
comparisons? If ‘yes’, give an example.
9. Does the µP have any special instructions for multiply/divide? If ‘yes’, give an example.
5 — 14
Summer 2004/V0.2
Experiment 5: Beyond Assembly Language
10.Does the µP have a fixed sized stack? If ‘yes’,
what is the size?
11. Can the µP write to the stack under program control? If ‘yes’, give an example on an instruction that
does this.
12. How many clock cycles does it take for an add
operation to execute?
13. How does the µP accomplish indirect addressing?
Give an example.
14. Give the machine code format for an add of two
register values (you pick the registers).
15. What flags are affected in the status register of the
µP by the add instruction? Give the definition of
each flag.
16. For the shift/rotate instructions, can multiple positions be shifted via one instruction? If yes, how
many clocks does it take for a multiple position
shift?
5 — 15
Experiment 5: Beyond Assembly Language
5 — 16
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 6: Bringing the PIC to Life
6
Bringing the PIC to Life
This lab makes your PIC 18F242
come alive. You will feel what Dr.
Frankenstein felt when his creation
took its first breath. OK...maybe
not. But you will breath a sigh of
relief when an LED turns on under
PIC control.
Summary:
Hook up power, reset, and the RS232 serial port for
your PIC. Verify functionality via the ledflash program. Verify that you can program your PIC using a
serial bootloader. Measure the current consumption
the PIC while in normal mode and sleep mode.
6—1
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
A. Prelab Requirements
Table 6–1: Prelab Checkoff
Do This
1.
Comments
Wire all connections
shown in the schematic.
You will not receive
prelab credit unless your
protoboard is fully wired
before lab (the headerto-modular connector will
be wire wrapped during
the lab period).
Do not have your PIC plugged into your board until you
have verified that the output of the voltage regulator is 5V.
Use the PIC 18F242 datasheet and the Prototyping Hints
appendix for more information on the parts.
WARNING: Only the wiring necessary to complete this
lab may be on your protoboard. This is to prevent you
from using a completed protoboard from a previous
semester, which would give you an unfair advantage
over your fellow students. It would also bypass one of
the principle educational tenets of this lab - how to
bring a microcontroller system to life from scratch.
Figure 6.1
Wall
Xfmr
If there are multiple
VDD/VSS pins on
your PIC, hook them
all up!!!
Fuse
Pic Startup Schematic
Note polarity of LED!!
Should turn on when
reset button is pressed.
10K
ohm
7805
Pwr
Conn
18F242
5V
9V
1.0µ
+
Vdd
Vss
470 ohm
Power on
LED
15 pf
Osc1
Crystal
Osc2
15 pf
RB1
470 ohm
6—2
Vpp/
Mclr
Reset
Switch
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
Table 6–2: Parts List
Part
Comments
1.
PIC18F242
28-pin Dual Inline Package (DIP)
2.
7.3728 MHz Crystal
2-pin Metal package
3.
Power connector (plug)
3-pin connector, has circular jack in middle
4.
7805 Power regulator
three pin package, has metal heat sink
5.
push button switch
4-pin package, small square push button
6.
3 LEDs
Choose a color, any color
7.
1.0 µf Capacitor or 0.1µf
capacitors (at least 6)
Will be 1.0 µf if your part kit has a MAXIM 232
transceiver; will be 0.1 µf if your part kit has a
MAXIM 202 transceiver. Note that the capacitors
you have in the parts kit are polarized, the + terminal is the longer lead, the ‘-’ terminal is the
shorter lead.
8.
15 pF Capacitors (2)
To be used with the crystal to create the clock for
the PIC; these capacitors are non-polarized so it
does not matter how you plug them in.
9.
5 pin header
Will use wire wrap to connect this to pins of the
external modular connector for the RS232 serial
port connection
10.
DC Wall Transformer
Be sure to use the one supplied in your parts kit.
If you use a different one, verify the polarity and
voltage value.
11.
470 ohm resistor pack
10-pin Single Inline Package (SIP), contains 5
resistors
12.
10K ohm resistor pack
10-pin SIP, contains 5 resistors.
13.
MAX232 or MAX202
RS232 transceiver
16-pin DIP
14.
DB9 connector
15.
In-line PCB Fuse
Two-lead printed circuit board slow-blow fuse
6—3
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
B. Lab Activity
Table 6–3: Initial Hookup Checkoff
Checkpoint
1.
Debugging
Before hooking up the PIC,
plug the wall transformer into
the power connector and use
the multimeter to verify that the
output of the 7805 voltage regulator is 5V.
Use the scope to check the
voltage level, and also verify
that power supply ripple is
within acceptable limits (+/300 mV or so).
Use the picture in the ‘Prototyping Tips’ appendix to discover the proper orientation of the
parts. Verify that the back pin of the power connector has +9 Volts (V). Verify that the pin from
the power switch to the 7805 switches from +9 V
to floating when switched. The ‘input’ pin of the
7805 is on the left side when viewed from the
front (the writing on the 7085 is visible). The output is on the right hand side, and the middle pin
is connected to ground. You will need to solder
wires on to the power connecter, then use these
wires to connect to the protoboard.
2.
Verify that the power LED
turns on when power is
switched on.
The short pin of an LED is the cathode and is
connected to ground.
3.
Use the scope and verify that
a sinusoidal waveform is
present on the OSC1 pin of
the PIC.
Verify the capacitor and crystal connections as
shown in Figure 6.1 .
4.
Verify that the reset LED turns
on when the reset button is
pushed.
Use the multimeter to determine which two pins
of the push button switch are connected when
the button is pushed. The resistance across
these two pins is zero when the button is
pushed.
5.
Give your PIC to the TA, and
have the TA program the PIC
with the ledflash program.
Plug the PIC back in the protoboard, and the LED attached
to port RB1 should flash.
If the LED does not flash, disconnect the LED
from RB1, and use the oscilloscope to check the
output waveform on the RB1 pin. The waveform
should be a square wave with a frequency of
less than 1 Hz. If there is no waveform, ask the
TA for assistance. If there is a waveform, then
the LED incorrectly connected.
DEMONSTRATE THAT THE LEDFLASH PROGRAM IS
WORKING CORRECTLY. HAVE THE OSCILLOSCOPE
DISPLAYING THE OSCILLATOR OUTPUT WAVEFORM
THAT IS PROVIDING THE CLOCK FOR THE
6—4
PIC.
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
Table 6–4: RS232 Serial Port Hookup
Checkpoint
1.
Make the connections for the
RS232 serial port as shown in
Figure 6.2 .
You will need to use wirewrap
for the connections between the
5-pin header and the DB9 connector. See Appendix A for tips
on wire-wrapping; a wirewrap
tool is available from the TA.
2.
Have the TA program your PIC
with the sercomm program.
Open a Hyperterminal window
(found under Programs →
Accessories → Communications). After typing in a name for
the session, select port COM1
with baud rate = 19200, 8 data
bits, 1 stop bit, and flow control
= NONE. Type a character, the
PIC should echo back the next
ASCII character in the sequence
(‘a’ echoed as ‘b’, ‘P’ as ‘Q’,
etc.).
Debugging
The MAX232/MAX202 provides 5 V conversion to the +/- 10 V voltage levels
required by RS-232 via external capacitors (not shown in the schematic below).
Use the MAX232/MAX202 datasheet and
connect all capacitors shown (your parts
kit will have 1.0 µF capacitors if using a
MAX232, else the capacitors will be 0.1
µF if using the MAX202). Be careful of the
polarity of the capacitors. The MAX232/
MAX202 provides two sets of drivers/
receivers; it does not matter which set is
used. However, you must be careful to
use the RIN/ROUT pins that are connected to the same buffer (ditto for the
TIN/Tout pins). The pinouts of the
MAX232 vs. the MAX202 are the same;
the only difference is the value of the
external capacitors and the total current
consumption of the part.
This program waits for a value to be ready
from the RXREG (typed from keyboard),
increments this value, then echoes this
character back to the TXREG of the serial
port (character will be displayed in Hyperterm).
For detailed debugging steps, see the
next section.
6—5
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
Figure 6.2
18F242
RS232 Serial Port Schematic
MAX232/MAX202
Rout
RC7/RX/DT
5 pin header
TX
Rin
DB9 Female
Pin 3
Gnd
Pin 5
Tin
RC6/TX/CK
Tout
RX
Pin 2
Header to DB9 connections are wire-wrapped
Figure 6.3
DB9 Connector Pinout
Front view: (looking into connector, pins facing up)
6
7
8
9
DB9 Female
1
2
3
4
5
4
5
Top view: (looking down on pins)
1
2
3
DB9 Female
6
Which pins are Tx and
Rx?
6—6
7
8
9
To determine if pin 2 (RX) and pin 3 (TX) are identified correctly, plug the DB-9 female connector into a
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
cable connected to the serial port on the laboratory PC.
Measuring the voltage between ground (pin 5) and TX
(pin 3, DB9) should produce a value of at least -8 V.
The RX (pin 2, DB9) is an input and will either be
floating (multimeter display fluctuating) or close to
ground.
The following debugging steps require use of the single trigger mode of the scope that allows a waveform
to be captured once a falling or rising edge is seen. See
Appendix B, steps 19-25 for information on how to
place the scope in this mode. If the sercomm program
does not work (no characters appear or garbled characters appear), try the following debugging steps in
order:
Detailed RS232 Serial
Port Debugging
• Verify that there is approximately +/- 10V on the
pins indicated in the MAX232/MAX202 datasheet.
This indicates that the capacitors are placed correctly.
• Verify the correct hyperterm settings of 19200
baud, no flow control. If garbled characters appear,
this means that the baud rate is set wrong.
• Determine if the typed character is reaching the
DB9 by placing the scope input on the TX pin of
the 5-pin header, and use Single trigger mode, rising edge triggered. The voltage level on the TX pin
of the DB9 should be approximately -8V when the
line is idle. Type a key on the keyboard, this should
cause the scope to trigger and capture the serial
waveform of the received character. If this does not
happen, then either the scope is configured wrong,
or the header pin is not connected to the TX pin of
the DB9. Move the scope input to the RIN pin of
the MAX202/232 and verify that the same character is being received at that point (if it is not, then
you have a wiring error between the header and
MAX232/202).
6—7
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
• Determine if the typed character is reaching the
PIC by placing the scope input on the ROUT pin of
the MAX232/202, and use Single trigger mode,
falling edge triggered (note that this triggering is
the reverse of the previous step). This voltage level
should be at +5V when the line is idle. Type a key
on the keyboard; this should cause the scope to trigger and capture the serial waveform of the received
character. If this does not happen, then either
power is incorrectly applied to the MAX232/202
part, or you have used a ROUT pin that is not associated with the RIN pin that you verified in the previous step. If you capture a character at this point,
then place the scope input on the RX pin of the PIC
and verify that the same character can be captured
at the PIC (if no character is seen, then check your
wiring).
• Determine if the received character is being transmitted by the PIC by placing the scope input on the
PIC TX pin, and use Single trigger mode, falling
edge triggered. This voltage level should be at +5V
when the line is idle. Type a key on the keyboard,
this should cause the scope to trigger and capture
the serial waveform of the transmitted character. If
this does not happen, then the PIC is either not
receiving the character in the first place (check the
previous step), the PIC was programed with the
incorrect program (not sercomm), or the PIC is
inoperative (check the clock waveform on the
OSC1 pin, voltage level of the board). If you capture a serial character on the TX pin of the PIC,
then move the scope trace to the Tin pin of the
MAX 232/202, and verify that the same character
is being received at that pin.
• Determine if the transmitted character is flowing
through the MAX202/232 by placing the scope
input on the Tout pin of the MAX202/232, and use
6—8
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
Single trigger mode, rising edge triggered. This
voltage level should be at approximately -8V when
the line is idle. Type a key on the keyboard, this
should cause the scope to trigger and capture the
serial waveform of the transmitted character. If this
does not happen, then the Tout pin being used is not
associated with the Tin pin used in the previous
step. After verifying that a character is being transmitted, move the scope input to the RX pin on the
5-pin header and verify that the transmitted character is present at that point.
If you have done all of the above debugging steps and
the sercomm program is still not executing correctly,
then seek TA assistance.
After you have verified the sercomm program, proceed to the next step of using the PIC18 bootloader
program.
What is next?
6—9
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
Table 6–5: PIC18 Bootloader
Checkpoint
Debugging
1.
Use the PIC18 C compiler, and
produce a hex file for the sercomm.c program listed on the
files link for this lab.
Follow the procedure given in the previous lab for using the PIC18 C compiler.
2.
Go to the ECE 3724 lab page,
and follow the Bootloader
Instruction Link for information
on using the PIC18 bootloader.
The PIC18 bootloader is installed on
the micro lab PCs; you may want to
test your board with this bootloader
before attempting to install the bootloader on your portable PC.
Program your PIC18 with the
sercomm.hex file using the
PIC18 serial bootloader.
However, you do eventually want to
verify that you can operate the PIC
bootloader via your portable PC as
this will allow you to work on lab exercises at home.
When using the bootloader,
there is a 2 second delay after
power up or reset before the
bootloader begins executing
the resident program - wait for
this time period before entering any input to the PIC.
WARNING: The best way to use the bootloader is to
turn off power to the PIC, press ‘PROGRAM’ in the
bootloader interface, then restore power to the PIC.
This ENSURES that the bootloader firmware in the
PIC has a chance to connect to the PC.
DEMONSTRATE TO THE TA THE PROGRAMMING OF
THE SERCOMM.HEX FILE USING THE PIC18 BOOTLOADER, AND THE OPERATION OF THE SERCOMM
PROGRAM. HAVE THE SCOPE INPUT ON THE TX PIN
OF THE PIC, AND THE SCOPE SET IN SINGLE CAPTURE
MODE, FALLING EDGE TRIGGER. DEMONSTRATE
THAT YOU CAN CAPTURE AND DISPLAY THE SERIAL
6 — 10
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
WAVEFORM OF THE CHARACTER BEING TRANSMITTED BY THE
PIC.
Table 6–6: Current Measurement of the PIC18
Checkpoint
Debug
1.
Compile the pertest.c program and
program it into the PIC18.
Verify its operation by opening a hyperterm
window with 19200 baud rate, no flow control. You will be presented with a menu
choice of three items after reset is pressed.
2.
Hook a multimeter in series with your
power supply to monitor the TOTAL
current being drawn by your board.
To monitor the total current, place the multimeter in series between the 7805 voltage
regulator and the power connector. Be sure
to use the mA and common terminals of the
multimeter, and choose the Dc/mA function.
3.
Fill in the current measurements in the table below.
To measure the current draw of the power LED, determine the different in current
draw when the power LED is inserted in the circuit, and when it is removed. To calculate the expected current draw, use the equation I = V/R; where V= (VDD - 0.7V) and
R = 470 ohms
To measure the current draw of the MAX232/202, determine the difference in current
draw when power is connected to the MAX232/202 and when it is disconnected.
Determine the expected value from the datasheet value for VCC power supply current.
To determine the current draw of the PIC in normal operation, place the PIC in sleep
mode via the menu choice and record the difference in total current draw. Determine
the expected value for PIC normal mode operation using the Typical IDD vs. FOSC
over VDD (HS/PLL mode) in the PIC18 datasheet.
The expected total current draw of your board is the sum of the expected current
draw of the individual components.
6 — 11
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
Table 6–6: Current Measurement of the PIC18
Checkpoint
4.
In the PIC bootloader, reload the pertest.hex file, but change the PIC configuration bits by selecting EDIT Config,
and change the bits to match below
(ensure HS option is chosen, LVP
option is unchecked, BODEN is
unchecked). Turn the PIC off, choose
Program Config, then turn power back
on to the PIC to allow the programing
to finish. Then cycle power on the PIC
for the new configuration bits to take
effect.
Re-measure the total power consumption of your board, and the power consumption of the PIC18.
6 — 12
Debug
The HS option disables the PLL circuit, so
the PIC will run 4 times SLOWER than previously (the HSPLL option causes the crystal frequency to be multiplied by 4X
internally to the PIC via a phase-lockedloop circuit). The Hyperterminal baud rate
must now be set at 4800 baud.
Measure the total board current draw and
the PIC current draw as previously. The
expected PIC18 current draw can be found
in the typical IDD vs. Fosc over VDD (HS
mode) graph in the PIC18 datasheet.
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
Record your measurements in the following table.
Table 6–7: Current Measurements
Measurement
1.
MAX202/232
2.
Power LED
3.
PIC18 (normal, HS/PLL)
4.
Total Power (HS/PLL)
5.
PIC18 (normal,HS)
6.
Total Power (HS)
Expected
Actual
%diff (ActualExpected)/
Expected*100
After the last measurements have been taken, re-program the configuration bits so that the HSPLL option
is chosen. Failure to do this will result in your PIC running 4X slower than it should (you can also get the TA
to reprogram your PIC with the original bootloader
hex file to turn the HSPLL option back on). When
configuration bits are changed, the PIC must be powered on and off for the changes to take effect.
HAVE THE TA INSPECT YOUR CURRENT MEASUREMENTS. DEMONSTRATE TO THE TA HOW YOU
OBTAINED THE MEASUREMENT FOR THE PIC18 IN
NORMAL MODE, USING THE HS CRYSTAL OPTION.
6 — 13
Experiment 6: Bringing the PIC to Life
Summer 2004/V0.2
C. Optional In-Circuit Programming Connection
Figure 6.4 below shows an optional in-circuit programming connection that can be connected; this is an
alternative to using the serial port and the bootloader
and requires the use of the ICD2 programmer (blue
hockey puck). This schematic is provided for reference purposes only; you DO NOT have to implement
this interface.
Figure 6.4 In-Circuit Programming Schematic
Note polarity of LED!!
Should turn on when
reset button is pressed.
10K
ohm
16F873
1.0µ
+
Vdd
OPTIONAL In-circuit
programming connection
Vpp/Mclr
Vpp/
Mclr
Vss
Vdd
Reset
Switch
Vss
1
2
3
4
5
RB7/
PGD
RB6/
PGC
RB7/
PGD
RB6/
PGC
Use 5-pin header for ISP connector.
The ordering of the pins is up to you,
but the picture in the prototyping
appendix has 1-to-5, right to left.
The 6-pin modular jack is available from Digikey, part
number A9084-ND.
6 — 14
Summer 2004/V0.2
Experiment 6: Bringing the PIC to Life
D. Report
1. In the pertest.c program, explain why the value for
‘reset cnt’ increments steadily each time the reset
button is pushed. What happens to the ‘reset cnt’
value when power is turned off/on? Why? What
bit/register of the PIC18 is being checked by the
pertest.c code to change this ‘reset cnt’ value?
2. For the pertest.c program, when option #3 is chosen (enable watchdog timer and sleep), the following sequence of events occur: a) user types ‘3’, b)
after a pause, the menu is re-displayed, c) after
another pause, the message ‘Watchdog timer reset
has occurred’ is displayed, followed by the menu
being displayed again. Clearly explain why this
sequence of events occurs from your reading of the
pertest.c code, and your knowledge of the watchdog timer and sleep mode operations.
6 — 15
Experiment 6: Bringing the PIC to Life
6 — 16
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 7: Serial versus Parallel
7
Serial versus Parallel
The nights of laying awake at night
wondering about that 9-pin connector on the back of your PC are over!
Rejoice! ....WhaTha? No sleepless
nights? Curious or not, prepare to
be initiated into the mysteries of
the 3-wire serial interface known as
RS-232.
Summary:
Write programs that: a) that reads an external switch
and controls an LED, b) uses the PIC parallel port to
test a 74XX device, c) queries the serial port for status
information.
7—1
Experiment 7: Serial versus Parallel
A.
Summer 2004/V0.2
Prelab Requirements
Table 7–1: Prelab Checkoff
Do This
Comments
1.
Make a good faith effort
at writing the ledswitch.c
program specified in
Table 7–2 , and demo to
the TA that it compiles
without syntax errors.
To save time in lab, you should make an attempt to write
all programs required by the lab before entering the lab so
that lab time can be spent debugging the programs.
2.
Draw the RS232 waveform for an 8-bit data
value, 1 start, 1 stop bit,
LSB sent first.
The 8-bit data value is based on the last digit of your Student ID as follows: 0) ‘e’, 1) ‘F’, 2) ‘n’, 3) ‘S’, 4) ‘3’, 5) ‘Z’, 6)
‘z’, 7) ‘#’, 8) ‘u’, 9) ‘p’. Use an ASCII table to determine
the 7-bit value of your character (the 8th bit is zero).
3.
Demo to the TA an Excel
spreadsheet that calculates the bit time in
microseconds for any
baud rate from 2400 to
115200.
Recall that a bit time is equal to one over the baud rate,
and that a microsecond is 10-6 seconds.
4.
Demo to the TA an Excel
spreadsheet that calculates the value to be written to the SPBRG
register given an oscillator frequency value, a
target baud rate, and
either high speed or low
speed baud rate mode.
The PIC18 datasheet section titled USART Baud Rate
Generator should prove helpful.
7—2
Summer 2004/V0.2
Experiment 7: Serial versus Parallel
B. Lab Activity
Table 7–2: ledswitch Program
If the last digit
of your
Student ID is...
Write a program called ledswitch.c to do:
0 or 5
Input push button is on RB2; LED flashes three times while the
push button is held down, then freezes off. When the pushbutton
is released, the LED freezes ON. LED is on port RB1.
1 or 6
Input push button is on RB2; LED flashes twice while the push
button is held down, and freezes off. LED flashes once when the
pushbutton is released, and freezes off. LED is on port RB1.
2 or 7
Input push button is on RB4, LED is initially ON. A press AND
release of the button starts the LED flashing SLOWLY; a subsequent press AND release changes the blink speed of the LED to
a noticeably faster rate. Each subsequent pushbutton press and
release changes the LED blink speed between slow and fast.
The LED is on port RB1.
3 or 8
Input push button is on RB4; LED flashes rapidly while the push
button held down, LED flashes three times slowly when the push
button is released, then freezes off. LED is on port RB1.
4 or 9
Input push button is on RB5; a press and release of the pushbutton causes the LED to blink twice fast, then once slowly, and
freeze off. A subsequent press and release starts the LED flashing rapidly. Each press and release changes between these
two sequences. LED is on port RB1.
The input pushbutton switch MUST BE configured as
a low true switch (i.,e produce a low voltage when the
button is pressed). Use a 10K pullup resistor to provide the high voltage.
DEMONSTRATE THE LEDSWITCH.C PROGRAM.
7—3
Experiment 7: Serial versus Parallel
Summer 2004/V0.2
Table 7–3: USART Error Checking
Checkpoint
1.
2.
Debugging
In the sercomm program from
the previous lab, the getch
subroutine waits for a character to be ready in the TXREG.
Modify this subroutine to
detect a framing error by
checking the FERR bit in the
USART status register
(RCSTA register). Turn on an
LED when an error is
detected. The LED should be
off after reset.
Use the following output port for your error status LED based on the last digit of your student
id: RB1 (0 or 1), RB2 (2 or 3), RB3 (4 or 5), RB4
(6 or 7), RB5 (8 or 9).
Change the baud rate from
19200 baud in Hyperterminal
and verify that a framing error
condition is produced.
Verify that you are checking the correct bit in the
RCSTA register. Framing errors occur when the
stop bit is detected as clear, which occurs when
the actual baud rate is lower than the expected
baud rate.
IMPORTANT!!! You must check the RCSTA
register for the framing error BEFORE reading the RCREG. Reading the RCREG
changes the value of the framing error bit to
the next character in the input FIFO.
USE THE SCOPE IN SINGLE TRIGGER CAPTURE MODE
TO CAPTURE THE CHARACTER APPEARING ON THE
RX PIN OF THE PIC. DEMONSTRATE THAT THE
CHARACTER WAVEFORM YOU CAPTURE MATCHES
THE WAVEFORM FOR THE CHARACTER YOU WERE
ASSIGNED IN PRELAB.
DEMONSTRATE THAT YOUR
PROGRAM DETECTS A FRAMING ERROR CONDITION.
7—4
Summer 2004/V0.2
Experiment 7: Serial versus Parallel
Table 7–4:
Checkpoint
1.
2.
Connect a 74XX gate as shown
in the schematic below. Use the
one provided in your part kit. You
can use any pins on port RB from
1 to 5 except the pin used for
your framing error LED.
Each 74XX package has four
gates, it does not matter which
gate is used.
Write a program called gatetest.c
that applies all four combinations
of gate inputs to the 74XX gate
and checks if the output value is
correct. Print a message indicating success or fail of the test.
Be sure that you understand how
your 74XX gate function works.
Test it independently before testing it with your program.
Your serial port must be configured with the baud rate given on
the right.
3.
Debugging
DO NOT USE PIN RB0. This
requires some extra configuration for correct operation.
Based on the last digit of your
Student ID, use the following
baud rate for your RS232 interface: 0,1 or 2: 38400; 3, 4 or 5:
57600; 6 or 7: 9600; 8 or 9:
115,200.
Try disconnecting an input or the
output and verifying that the test
fails.
18F242
74xx
RB?
RB?
RB?
7400 NAND
7402 NOR
7408 AND
7432 OR
7486 XOR
Figure 7.1 74XX gate connection to 18F242
Use the C function printf to send strings to the serial
port. The following:
Formatted IO via printf
7—5
Experiment 7: Serial versus Parallel
Summer 2004/V0.2
printf (“Hello World”);
will send the string “Hello World” to the Hyperterminal window. The following should print the same
string followed by a new line (carriage return, line
feed):
printf (“Hello World\n”);
For some reason, the new line (‘\n’) is not recognized
by Hyperterminal, so use:
putch(0x0a);putch(0x0d);
This sends the ASCII codes for a newline followed by
a carriage return. Put this in a subroutine called pcrlf
as it is a common operation.
gatetest Program Operation
Output from the gatetest program should appear something like the following:
Hit any key to begin test...
Gate Passed!
Hit any key to begin test...
Gate Failed!
Hit any key to begin test...
Use the getch subroutine to wait for the user to type a
key to begin a test; test the gate; indicate pass or fail;
then loop to start.
DEMONSTRATE YOUR GATETEST PROGRAM. SHOW
BOTH SUCCESS AND FAIL CASES.
7—6
Summer 2004/V0.2
Experiment 7: Serial versus Parallel
C. Report
1. Include source code listings of any C programs.
2. Include all pre-lab material; include a screen shot
of your Excel spreadsheet operation.
3. Discuss what problems can occur if a pushbutton
switch is connected as shown below.
4. The error tolerance for bit time mismatch between
receiver and transmitter in RS232 over 10 bits is
5%. For a crystal frequency of 7.3728 MHz, and a
PIC oscillator option of HSPLL, what is the MAXIMUM value that can be written to the SPBRG for
a baud rate of 19200 that will still be within this
error tolerance?
18F242
Pic Input
Push button,
momentary
closure when
pushed.
7—7
Experiment 7: Serial versus Parallel
7—8
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 8: Interrupt-Driven IO
8
Interrupt-Driven IO
Ahhh...how sweet life would be
without interruptions; no need for
alarm clock bashing, cussing at telephone solicitors, withering glares at
students knocking on the
door....<cough>. However, life in the
microprocessor world would be
tough without interrupts. How so?
Read on, young grasshopper, and
find enlightenment - or at least
your next assignment.
Summary:
Given a program that uses interrupt-driven serial
input, modify it to use a circular buffer for data storage. Also add error checking for buffer overrun and
framing error, and a choice of multiple baud rates.
8—1
Experiment 8: Interrupt-Driven IO
A.
Summer 2004/V0.2
Prelab Requirements
Table 8–1: Prelab Checkoff
Do This
Comments
1.
Wire all connections
shown in the schematic.
You will not receive
prelab credit unless your
protoboard is fully wired
before lab.
Based on the last digit of your student ID, use
the following two pins for the DIP switch: a) 0, 1,
or 2 use RB5/RB4; b) 3 or 4 use RB4/RB3; c) 5
or 6 use RB3/RB2; d) 7, 8, or 9 use RB2/RB1.
You may use any other ports from RB1 to RB5
for the framing and overrun error LEDs.
2.
Give the expected bit
time in microseconds
for each baud rate
selected by the DIP
switch.
Table 8–3 contains your assigned baud rates.
DIP Switch
18F242
Baud Rate
selection
RB?
RB?
RB?
470 ohm
RB?
Framing
error
overrun
470 ohm
Figure 8.1 Baud Rate Selection and Error Indication
8—2
Summer 2004/V0.2
Experiment 8: Interrupt-Driven IO
B. Lab Activity
The doroot program linked to this lab inputs a decimal
number in ASCII format, computes the integer square
root, and displays the result. The serial port is used for
all I/O (115,200 baud is the default baud rate). This
program uses an interrupt approach for serial input.
When the USART receives a character, an interrupt is
generated that causes the subroutine pic_isr to be
called. This subroutine stores the received character in
a memory location, and sets a flag (got_char) indicating an available character. The getch subroutine
checks this flag instead of the RCIF bit to determine
character availability. Note that the getch subroutine
clears the got_char flag when it is called. Read this
program and understand how the serial IO is performed (do not worry about understanding the operation of the sqroot subroutine).
The doroot program is the starting point for your modifications. Create different versions of this program as
you advance through the lab, so that a previous version
can be used if an approach yields unsatisfactory
results.
Table 8–2: Baud Rate Selection/Error Detection Checkoff
Checkpoint
1.
Program your PIC with the doroot
program and familiarize yourself
with its operation. Type in one
number at a time and verify that
the integer square root is computed.
Comments/Debugging
Remember to set all of the correct options to the
Hyperterminal program.
When compiling doroot.c, use the
‘-lf’ compile option so that the
floating point numbers print correctly.
8—3
Experiment 8: Interrupt-Driven IO
Summer 2004/V0.2
Table 8–2: Baud Rate Selection/Error Detection Checkoff
Checkpoint
2.
Open the file test1.txt in Notepad,
and select/copy a range of input
values, and use the Hyperterminal ‘Edit → Paste-to-Host’ command to copy this selection into
the terminal window. What happens when a large number of
entries is pasted at a time?
Comments/Debugging
You should observe that the doroot program will
operate correctly for a small number of entries
pasted into the window, but not for a large number. The failure is due to simultaneously receiving characters during transmission of the result
string. While characters are being transmitted,
the receive port is not checked. At some point,
the RCREG input FIFO buffer fills to capacity,
and characters are lost.
NOTE: When the Paste-to-Host command in
Hyperterminal is used, each character is sent at
the specified baud rate. However, there is considerable dead time between each character
that is sent (why? Unknown, poor programming
in Hyperterminal or other tasks in windows taking time). This explains why it takes more than
the expected number of input characters to
cause a buffer overrun problem.
If you cannot get overrun to occur using your
portable PC, try using the lab PC to communicate with your PIC.
3.
4.
8—4
Modify the doroot.c program to
use the DIP switch to select
between 4 different baud rates
after reset. Enable the weak-pullup on the Port B pins. External
pullups are not required for these
inputs. Table 8–3 contains your
assigned baud rates. Examine
the serial_init() subroutine in the
serial.c include file to understand
how to pass in values for the
SPBRG register and how to
select between low and high
speed mode.
Use a multimeter to verify the close/open positions of the DIP switch. Test all four baud rates.
Use an oscilloscope, and capture a character
waveform. Be prepared to show the TA that the
bit time of the captured waveform matches the
expected bit time.
Modify the pic_isr subroutine to
turn on an LED when a framing
error is detected.
The RCSTA register that contains the FERR bit
must be read BEFORE the RCREG. Once the
error LED is turned on, leave it on. Test the program with mismatched baud rates to determine
if a framing error can be detected (HINT: Hyperterminal must use a SLOWER baud rate than
the PIC expects to generate a framing error).
You may need to use the low speed mode to
reach some of your assigned baud rates.
Summer 2004/V0.2
Experiment 8: Interrupt-Driven IO
Table 8–2: Baud Rate Selection/Error Detection Checkoff
Checkpoint
Comments/Debugging
5.
Modify the pic_isr subroutine to
turn on an LED if an overrun error
occurs. This is not the same as
the USART overrun error. This
overrun error occurs if the pic_isr
subroutine is called, and the
got_char flag is already set, indicating that the previous character
has not been read.
If the got_char flag is already set when the
pic_isr subroutine is called, then reading and
storing the current transmitted character will
overwrite the old character, causing it to be lost.
Once the error LED is turned on, leave it on.
After an overrun error, do not read RCREG. Test
the program by pasting several numbers into the
Hyperterminal window, causing buffer overrun.
6.
Determine the relationship
between baud rate and the number of pasted selections required
to cause overrun. Record the
minimum number of entries
(within 3 or 4) needed to cause
buffer overrun for 4800 and
115200 baud.
Be prepared to discuss the ‘whys’ of the relationship between baud rate and the number of
entries required for overrun with the TA.
Table 8–3: Baud Rate Assignment
If the last digit
of your
Student ID is...
Use the following baud rates for your DIP switch
(switch assignment is up to you)
0 or 1
4800, 19200, 57600, 115200
2 or 3
4800, 38400, 57600, 115200
4 or 5
4800, 9600, 38400, 115200
6 or 7
4800, 9600, 57600, 115200
8 or 9
4800, 19200, 38400, 115200
DEMONSTRATE YOUR BAUD RATE SELECTION AND
ERROR DETECTION. CAPTURE A CHARACTER WAVEFORM AND USE THE OSCILLOSCOPE CURSORS TO
MEASURE THE BIT TIME.
COMPARE THIS BIT TIME TO
THE EXPECTED BIT TIME.
8—5
Experiment 8: Interrupt-Driven IO
8—6
Summer 2004/V0.2
Summer 2004/V0.2
Experiment 8: Interrupt-Driven IO
The doroot program is attempting two things at once:
print a result while also receiving new input. The interrupt-driven input allows the PIC to interrupt the printing of the result to read an input character. However,
the current implementation only has a single character
location to store the incoming character. If the interrupt subroutine is called again before the current result
is finished printing, a character is lost.
The Overrun Problem
To fix this problem, use more than one location to
store incoming characters. A circular buffer (or circular FIFO) data structure is typically used for this. First,
a set of locations is reserved for storing characters,
such as:
Fixing the Problem
volatile bdata unsigned char ibuf[BSIZE];
The ibuf array is used to stored incoming characters.
The bdata designator is used to allocate this storage in
a bank other than the access bank of the PIC as allows
changes to the buffer size without depleting the available access bank memory. The volatile designator
informs that compiler that this will be used within an
interrupt service routine, and thus can change at any
time. The BSIZE define sets the buffer size; use a
value of 16 initially.
Two pointers, called the head and tail respectively, are
used to store and retrieve values from the buffer.
Storing/Retrieving values from a circular buffer
volatile unsigned char head;
volatile unsigned char tail;
When a character is received, the head pointer is incremented, and the character stored at ibuf[head]. To
retrieve a character from the buffer, increment the tail
pointer, then read the character from ibuf[tail]. When a
head/tail pointer is incremented, check if it is equal to
8—7
Experiment 8: Interrupt-Driven IO
Summer 2004/V0.2
BSIZE; if yes, then set the value to 0. In this way, the
head/tail pointer wraps around to location 0 in the
buffer (hence the name, circular buffer).
Empty, Not-empty, Full
The initial values of the head and tail pointers are 0. If
head == tail, then the buffer is empty. If head != tail,
then characters are available in the buffer. Recall that
when a character is placed into the buffer, the head
pointer is incremented. After the head pointer is incremented (and wrapped to 0 if necessary), if head ==
tail, then the buffer is full (actually, by these definitions there is room for one more character, but call this
the full condition to simplify buffer operation).
Implementing a circular buffer for input storage allows
an interrupt-driven input system to tolerate bursts of
input activity without data loss. However, no amount
of buffering can prevent data loss if the rate that data is
placed into the buffer is faster than the rate that data is
taken out of the buffer for an extended period of time.
Table 8–4: Circular Buffer Checkoff
Checkpoint
1.
2.
8—8
Comment/Debugging
Create a new version of the
doroot.c program that implements circular buffering. Use a
buffer size of 16. Turn on the
overrun error LED if the buffer
full condition is detected.
This requires modification of the getch and
pic_isr subroutines. The getch subroutine waits
until data is available, then removes one character from the buffer. The pic_isr subroutine places
data into the buffer and performs error checking.
Determine how circular buffering has changed the number
of entries required to cause
overrun. Use the baud rates
that you recorded overrun values for previously.
When determining the number of entries needed
to cause overrun, exact values are not needed
(+/- 5 entries is close enough)
Start simple and test the program for manually
typed input. Then test it using the Paste-To-Host
feature of Hyperterminal. Do not forget to wrap
the head and tail pointers to 0 if they are equal
to the maximum buffer size after incrementing
them.
Summer 2004/V0.2
Experiment 8: Interrupt-Driven IO
DEMONSTRATE YOUR PROGRAM VERSION THAT
IMPLEMENTS CIRCULAR BUFFERING. DISCUSS THE
OVERRUN BEHAVIOR BEFORE AND AFTER CIRCULAR
BUFFERING FOR DIFFERENT BAUD RATES.
C. Report
1. Include source code listings of any C programs.
2. Give the bit time for each of your assigned baud
rates.
3. Discuss the overrun behavior before and after circular buffering for different baud rates.
4. The overrun condition that is being checked in this
lab is different from the OERR bit (Overrun error
bit) in the RCSTA register (UART status register).
In the original doroot.c code (or any of the successive versions that you write), the OERR bit in the
RCSTA register will NEVER be set. Why is this?
What is the fundamental property of the doroot.c
code that prevents the OERR bit from being set?
5. To generate a framing error, Hyperterminal must
use a slower baud rate than what the PIC expects.
Why is this so? Explain in detail, and draw a diagram to support your argument.
8—9
Experiment 8: Interrupt-Driven IO
8 — 10
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 9: Memory and the I2C Bus
9
Memory and the I2C Bus
Memory is a good thing! Why, without memory, microprocessors would
have difficulty with many things,
such as transforming into rouge AIs
that take over the world, enslaving
the human race for use as Duracell® batteries. And, without memory, where would you store your
65th level über Everquest van Shir
Beastlord? Motivated? Not?
Onwards anyway!
Summary
Explore the workings of the I2C bus via a serial
EEPROM. Write a program that uses page write mode
to store a file sent via the serial port into the
EEPROM. Verify the file was saved by using sequential reads to display the contents of memory.
9—1
Experiment 9: Memory and the I2C Bus
Summer 2004/V0.2
A. Prelab Requirements
Table 9–1: Prelab Checkoff
Do This
Comments
1.
Wire all connections shown in the schematic. You will not receive prelab credit
unless your protoboard is fully wired
before lab.
Use the 10K resistor SIP for the pull-ups.
These are required because the drivers
on the SCL, SDA lines only have pulldown capability because multiple connections may be made to these lines.
2.
Become familiar with the memblk.c program attached to this lab. This program
uses subroutines from the i2cmsu.c file.
Modifications to this program are required
as part of this lab, so understanding the
behavior of this program is essential to
success. Refer to the 24LC511 datasheet
for details on the read/write operations for
this device.
3.
Demo to the TA an Excel spreadsheet
that will calculate the correct SSPADD
value for a desired I2C bus speed.
Use crystal frequency 7.3728 MHz,
HSPLL mode.
18F242
Vdd
Microchip 24LC515
10K
RC3/SCK/SCL
Vdd
SCL
Vdd
A2
A1
10K
RC4/SDI/SDA
SDA
A0
If you have trouble
distinguishing which 8pin DIP in your parts kit
is the 24LC515, look
for the Microchip
symbol on the package.
The 10K pullups are very important!!! The I2C bus will not work without
them. The WP pin on the 24LC515 can be left unconnected.
Figure 9.1 PIC to Serial EEPROM connection
9—2
Summer 2004/V0.2
Experiment 9: Memory and the I2C Bus
B. Lab Activity
The memblk program performs either a page write or
sequential read operation to the serial EEPROM. In
write mode, a page of 64 bytes is captured from the
serial port and written as one page to the EEPROM. In
read mode, 64 bytes are read sequentially from the
EEPROM and then displayed via the serial port.
The serial EEPROM read/write functions and basic
I2C functions are in the file i2cmsu.c. This file must be
included as part of the project source files during compilation. Familiarize yourself with the available functions in the i2cmsu.c file.
Table 9–2: Serial EEPROM Operation Checkoff
Checkpoint
Comments/Debugging
1.
Verify that the memblk
program operates correctly on your protoboard.
Use the file test.txt and the ‘Paste-to-Host’ functionality of Hyperterminal to test the program
with different groups of 64 characters.
2.
Change the wiring of the
A1/A0 pins to alter the
address of the EEPROM.
Modify the memblk program to use this new
address.
Use the following values for A1/A0 based on the
last digit of your student ID: a) 0,1,2 use ‘01’; b)
3,4,5 use ‘10’; c) 6,7,8,9 use ‘11.
Modify memblk to prompt
the user to choose one of
two different I2C bus
rates. One rate is 500
KHz (or as close as you
can achieve), and the
other is specified on the
right.
Use the following I2C bus speeds based on the
last digit of your student id: a) 0 or 1 (50 KHz), b)
2 or 3 (100 KHz), c) 4 or 5 (175 KHz), d) 6 or 7
(250 KHz), e) 8 or 9 (325 KHz).
3.
The ‘#define ROM 0xA0’ statement in memblk.c
must be changed to accommodate the new A1/
A0 values. Review the command byte formatting
in the 24LC515 datasheet to determine the new
value.
Even though 500 KHz is above the maximum
specification for the memory part, it should still
work as datasheet specifications are very conservative. However, this is only being done for
illustrative purposes. Never design a system
that relies on a part working beyond its specified
performance.
9—3
Experiment 9: Memory and the I2C Bus
Summer 2004/V0.2
DEMONSTRATE THE OPERATION OF MEMBLK USING
THE MODIFIED EEPROM ADDRESS WITH YOUR
ASSIGNED I2C BUS SPEED. CAPTURE THE FIRST 5
BYTES OF A PAGE WRITE OR SEQUENTIAL READ VIA
THE OSCILLOSCOPE AND EXPLAIN THE FORMATTING/
PURPOSE OF EACH BYTE TO THE
TA. USE A PAGE
WRITE IF THE LAST DIGIT OF YOUR STUDENT ID IS
ODD, ELSE USE A SEQUENTIAL READ. ON THE SCOPE,
HAVE BOTH
SCL AND SDA DISPLAYED AND SHOW
THAT YOU HAVE ACHIEVED THE SPECIFIED BUS
SPEED.
AFTER THIS, DEMONSTRATE OPERATION AT
THE 500 KHZ BUS SPEED.
Streaming writes
Capture 64 bytes
from serial port to
buffer
Page Write of 64
bytes
Use two buffers
9—4
The memblk program captures 64 bytes from the serial
port and uses a page write to save this to the
EEPROM. What is needed to support the saving of a
continuous stream of data from the serial port to the
EEPROM?
The problem with the operation on the left is that during the page write operation, more bytes are arriving
via the serial port. These bytes must be buffered by the
input interrupt service routine somewhere so that they
are not lost during the page write.
The solution to this problem is to use two buffers.
When one buffer is being written to the EEPROM, the
other buffer is used for storing data, and vice-versa.
Summer 2004/V0.2
Experiment 9: Memory and the I2C Bus
The flowchart below shows how to modify the interrupt service routine to use two buffers.
Char arrival
triggers interrupt
0
Interrupt Service
Subroutine
1
Active buffer?
Save char in buff0
no
64 bytes?
Save char in buff1
no
64 bytes?
yes
yes
Write_flag = 1
Write_flag = 1
exit interrupt service
Note that two variables are used, active_buffer and
write_flag. The active_buffer variable indicates the
buffer used for incoming data. The write_flag variable
is set when a buffer is full, requiring a page write to
EEPROM.
The flowchart below shows how to implement streaming IO using this two buffer scheme. The addr value is
incremented by 64 each time a page write is performed. Because addr is a 16-bit integer, its value will
wrap to zero once 64K bytes are written. Check for
9—5
Experiment 9: Memory and the I2C Bus
Summer 2004/V0.2
addr == 0 (64K) after it is incremented by 64 and halt
writing if true as memory is full at this point.
Streaming Write Loop
0
Write_flag?
Wait for interrupt service
routine to fill a buffer.
1
0
Active buffer?
1
Active buffer = 1
Active buffer = 0
Page write buff0
Page write buff1
Write_flag = 0
addr = addr + 64
Checking for Overrun
9—6
An overrun check should be placed in the interrupt service routine. The condition of write_flag==1 when a
buffer becomes full indicates that the previous write
has not completed. However, overrun will not happen
in this testing environment. At the maximum baud rate
of 115200, it takes approximately 5.5 ms to send 64
bytes. Even though individual characters are sent at
this rate, Hyperterminal has excessive dead time
between characters, so a block write is finished long
before the second buffer fills up. However, in a later
lab, this same technique is used and overrun checking
is necessary.
Summer 2004/V0.2
Experiment 9: Memory and the I2C Bus
Table 9–3: Streaming IO Checkoff
Checkpoint
1.
Using memblk as a starting
point, create a program that
implements streaming writes.
Verify that your program works
for your assigned I2C bus
rates.
Comments/Debugging
Use the flowcharts to help you understand how
to solve this problem.
Test your program by using the ‘Transfer →
Send Text File’ command in Hyperterminal to
send a complete file. Do not use large files for
test cases as HyperTerminal takes too long to
send text files even with a baud rate of 115200.
Your streaming write program should do something
like the following:
Program Operation
Enter ‘r’ for read, ‘w’ for
write...
If ‘w’ is entered, then capture bytes from the serial
port and write to the EEPROM using page mode. Print
a ‘*’ character for each block written so there is visual
evidence of program operation. Stop writing once 64K
is written.
If ‘r’ is entered, dump the memory contents to the
screen. Have a single keypress halt the output, the next
keypress resumes character output. Stop reading if
64K bytes is read. When printing a character, use:
putch(c);
where c is the character to be printed. To allow
Hyperterminal to display the text with carriage return/
line feeds, add the check:
if ((c == 0xd) || (c == 0xa))
pcrlf();
else putch();
This causes end-of-lines to display correctly in Hyperterminal.
9—7
Experiment 9: Memory and the I2C Bus
Summer 2004/V0.2
DEMONSTRATE YOUR STREAMING WRITE PROGRAM;
BOTH WRITE AND READ CAPABILITIES.
C. Report
1. Include source code listings of any C programs.
2. Discuss how the 24LC515 handles a random read
or write to an address above 0x7FFF.
3. For your assigned I2C bus rate, compute the time
required to perform a page write - the includes the
time to specify the initial address, transfer the 64
bytes, and the 5 ms write time.
4. Explain the difference between a random read and
a sequential read for the 24LC515.
5. Based on the last digit of your student ID, explain
the reasoning behind each line of the one of the following subroutines in the file i2cmsu.c: 0 or 1 use
i2c_idle(), 2 or 3 use i2c_stop(), 4 or 5 use
i2c_start(), 6 or 7 use i2c_putbyte(), 8 or 9 use
i2c_getbyte().
9—8
Summer 2004/V0.2
E x p e r i m e n t
Experiment 10: Talking to the Real World
1 0
Talking to the Real World
It is a fact of life that our pristine
digital domain must talk to devices
that live in the brutish analog world
will all of its messiness of voltages,
currents, noise, etc. The silver lining is that with communication
comes control, and with control
comes world domination! Keeping
this goal firmly in mine, proceed in
discovering the secrets of DACs
and ADCs.
Summary
Use the PIC on-chip Analog-to-Digital Converter
(ADC) with an external I2C-based Digital-to-Analog
converter (DAC) to form the basis for a signal processing system.
10 — 1
Experiment 10: Talking to the Real World
Summer 2004/V0.2
A. Prelab Requirements
Table 10–1: Prelab Checkoff
Do This
Comments
1.
Wire all connections shown in the schematic. You will not receive prelab credit
unless your protoboard is fully wired
before lab.
2.
Become familiar with the operation of the
dactst.c program attached to this lab.
3.
Demo to the TA a spreadsheet that calculates a ADC output voltage given a Vref,
an input code value, and number of ADC
input bits.
Example: For Vref = 5 V, input code of 128
(decimal), number of bits = 8, the output
voltage is 2.5 V. The Excel functions
POWER(x,y); DEC2HEX(x), HEX2DEC(x)
are useful (the hex conversion is
optional).
4.
Demo to the TA a spreadsheet that calculates a DAC output code given a Vref, Vin,
and number of DAC output bits.
Example: For Vref = 5 V, Vin = 2.5 V,
number of bits = 8, the output code should
be 128.
Analog
input
Vdd
Analog out, To
multimeter or scope
18F242
RA0/AN0
10K Pot.
Be sure to connect the OUT1 pin of the
MAX517 to Vdd - this serves as the reference voltage input to the DAC.
Maxim 517
OUT1
OUT0
AD1
RC3/SCK/SCL
SCL
RC4/SDI/SDA
SDA
AD0
Vdd
If you have trouble
distinguishing which
8-pin DIP in your
parts kit is the
MAX517, look for the
Maxim symbol on the
package.
This diagram assumes that 10K pullups are already on the SCL/SDA
lines from the previous lab.
Figure 10.1 PIC to I2C DAC connections
10 — 2
Summer 2004/V0.2
Experiment 10: Talking to the Real World
B. Lab Activity
The dactst.c program attached to this lab uses the onchip ADC to convert an external voltage to a 10-bit
value and prints this value to the serial port as ASCII
hex. It then drops the two LSBs of the 10-bit conversion and sends the 8-bit value to the MAXIM 517
DAC.
Start ADC
conversion
Conversion No
complete?
Table 10–2: dactst.c Checkoff
Comments/
Debugging
Checkpoint
1.
2.
Verify that the dactest.c
program functions on
your board.
Complete the measurements/computations
listed in Table 10–3 and
Table 10–4.
Verify that SCL, SDA
are connected correctly to the MAX517
and that the AD0, AD1
pins are grounded.
Use the same probe
for all measurements.
Yes
Read 10-bit ADC
value, print to
serial port
Convert 10-bit to
8 bit value by
dropping 2 LSBs
Send 8-bit value
to DAC
Table 10–3: ADC Measurement
Measurement
Value
a) Vdd (measure this value!)
b) 1 LSB (Vdd/1024)
c) PIC RA0 input voltage when displayed code is 0x200 (this should be
Vdd/2 but may not be because of offset voltage)
d) PIC RA0 input voltage when displayed code is 0. This is the offset
voltage.
e) Corrected Input voltage for code=0x200 (c - d)
f) Absolute Error = Expected (Vdd/2) - Corrected (e)
g) Relative Error in LSBs ((f) / 1 LSB)
An acceptable error is less than 1/2 LSB
10 — 3
Experiment 10: Talking to the Real World
Summer 2004/V0.2
Table 10–4: DAC Measurements
Measurement
Value
a) Vdd (measure this value!)
b) 1 LSB (Vdd/256)
c) MAX517 output voltage when displayed code is 0x200 (this should be
Vdd/2 but may not be because of offset voltage)
d) MAX517 output voltage when displayed code is 0. This is the offset
voltage.
e) Corrected Input voltage for code=0x200 (c - d)
f) Absolute Error = Expected (Vdd/2) - Corrected (e)
g) Relative Error in LSBs = ((f) / 1 LSB voltage)
An acceptable error is less than 1/2 LSB
The use of Vdd as a reference voltage is not sufficient
for precision data conversions; the voltage ripple on
Vdd is usually several LSBs for a 10-bit converter.
Stand-alone integrated circuits are available that provide a stable voltage reference.
DEMONSTRATE DACTST OPERATION ON YOUR PROTOBOARD. CAPTURE A WRITE CYCLE ON THE I2C
BUS TO THE MAX517 AND EXPLAIN THE BYTE FORMATTING TO THE TA. DISCUSS YOUR MEASUREMENT
RESULTS WITH THE TA.
10 — 4
Summer 2004/V0.2
Experiment 10: Talking to the Real World
Table 10–5: dactst Modification Checkoff
Checkpoint
1.
2.
Comments/Debugging
Change the wiring of the
AD1/AD0 pins to alter
the address of the DAC.
Modify the dactest program to use this new
address.
Modify the dactst program to allow the user to
choose one of 4 different transformations to
the output waveform: a)
clipping, b) multiply by
two, c) divide by two, d)
inversion.
Use the following values for AD1/AD0 based on
the last digit of your student ID: a) 0,1,2 use ‘01’;
b) 3,4,5 use ‘10’; c) 6,7,8,9 use ‘11.
The ‘#define DAC 0x58’ statement in dactst.c
must be changed to accommodate the new A1/
A0 values. Review the address byte formatting
in the MAX517 datasheet to determine the new
value.
Use the clipping ranges as shown in the table
below based upon the last digit of your student
ID.
Use shifts to do the multiply by two or divide by
two.
Inversion means that the input voltage value
should be subtracted from the maximum value.
For example, if input_value is the non-inverted
8-bit output value for the DAC, then the inverted
value would be 0xFF - input_value.
Table 10–6: Clipping Ranges
If the last digit
of your
Student ID is...
Your clipping range is...
0
between 1.1v and 4.3v
1
between 1.3v and 3.9v
2
between 0.8v and 4.1v
3
between 0.9v and 4.2v
4
between 1.2v and 4.4v
5
between 1.0v and 4.0v
6
between 1.4v and 3.8v
7
between 1.6v and 4.6v
8
between 1.5v and 4.5v
10 — 5
Experiment 10: Talking to the Real World
Summer 2004/V0.2
Table 10–6: Clipping Ranges
If the last digit
of your
Student ID is...
9
Your clipping range is...
between 1.7v and 3.7v
Your program should prompt the user as shown below:
Operation choice:
0: inversion
1: multiply by 2
2: divide by 2
3: clipping
Enter choice:
DEMONSTRATE YOUR PROGRAM USING THE MODIFIED DAC ADDRESS.
C. Report
This is a formal lab report; be sure to follow the formatting guidelines posted on the lab web site.
1. Include source code listings of any C programs.
2. Include all DAC and ADC measurements.
Formal Report Questions
The following questions refer to the non-PIC microcontroller you are assigned via the lab web site.
3. What serial standards are supported with on-chip
modules by your µP? Asynchronous serial trans-
10 — 6
Summer 2004/V0.2
Experiment 10: Talking to the Real World
mission? SPI? I2C? What is the maximum synchronous transfer rate?
4. Does it have an on-chip A/D? If ‘yes’, what is the
precision?
5. Does it have an on-chip DAC? If ‘yes’, what is the
precision?
6. How are the special registers of the on-chip modules accessed? What is the range of memory
addresses that correspond to these special registers?
7. At reset, what location is the first instruction
instruction fetched from?
8. What are the minimum and maximum package
sizes in terms of pin count? For the maximum
package size, how many parallel port lines are
available?
9. What is the maximum system clock frequency?
10.What is the minimum Vdd supported by the processor (This is the minimum Vdd the processor will
operate at for normal operation; it is not the value
in the ‘absolute maximum rating’ section of the
datasheet; so do not give any negative values for
this, please!).
10 — 7
Experiment 10: Talking to the Real World
10 — 8
Summer 2004/V0.2
Summer 2004/V0.2
E x p e r i m e n t
Experiment 11: Controlling Time
1 1
Controlling Time
The PIC18Fxx2 is capable of
sophisticated time measurement
and manipulation. Unfortunately,
this does not include the capability
to travel either forwards or backwards in time; only the PICT3000
can do that and it is currently busy
looking for somebody named ‘Conner’. Alas, we have to stick to mundane things like precise waveform
generation and leave time travel for
grad school.
Summary
Pulse Width Modulation (PWM) is explored using the
PIC PWM module, and waveform generation is performed using the PIC timer modules.
11 — 1
Experiment 11: Controlling Time
Summer 2004/V0.2
A. Prelab Requirements
Table 11–1: Prelab Checkoff
Do This
1.
Comments
Connect the audio jack connector to the
output of the DAC.
Also connect an LED to pin ‘RC2/CCP1’
of the PIC, and the 10K potentiometer to
the RA0/AN0 input.
2.
Demo to the TA a spreadsheet that calculates the values required for Table 11-3.
Your assigned target frequencies are in
Table 11-2.
The frequencies in Table 11–2 use the
PWM mode for generating the square
wave; this does NOT use the postscaler
for frequency calculation.
3.
The audio jack allows an external speaker
to be driven by the DAC output. This
capability is crucial for the last experiment, so it is tested in this experiment.
The spreadsheet should calculate the
PR2 values given a target frequency, and
prescaling factors of 1, 4, and 16. The
spreadsheet should also truncate the PR2
value to an integer value, then compute
the %diff between the actual frequency
obtained and desired frequency. Choose
the pre-scale and PR2 value that gives
the lowest %diff value.
Become familiar with the sqwave.c, ledpwm.c, and sinegen.c programs attached
to this lab.
Maxim 517
Audio mini
To determine which pin is ground on the jack, plug a cable from
jack
the line out of the PC into the jack, and use media player to
play a MP3. Measure the voltage on the pins of the jack and
determine the pin orientation provides a positive voltage. Do
this before connecting the DAC to the jack. Do not attempt to
plug the mini-jack into the protoboard; solder wires onto the
connections for a more reliable connection.
OUT0
Table 11–2: Assigned Frequencies
If the last digit
of your student
ID is...
11 — 2
Use these frequencies
0 or 1
2500 Hz, 10 KHz, 121 KHz
2 or 3
3600 Hz, 15 KHz, 133 KHz
Summer 2004/V0.2
Experiment 11: Controlling Time
Table 11–2: Assigned Frequencies
If the last digit
of your student
ID is...
Use these frequencies
4 or 5
4200 Hz, 28 KHz, 144 KHz
6 or 7
5500 Hz, 37 KHz, 151 KHz
8 or 9
6100 Hz, 49 KHz, 165 KHz
Fill in the table below for your three assigned frequenTable 11–3: Prescale, PR2 Values
Target
Frequency
Prescale
PR2
Actual Freq
% diff
a)
b)
c)
cies. There might be more than one solution using different prescale values; use the prescale value that gives
the best match for the target frequency. The ‘Actual
Frequency’ column is the computed value using the
prescale and PR2 values using the formula:
PWM period=[(PR2)+1]*4*TOSC*Pre
Freq = 1/(PWM Period)
Tosc = 1/(Osc. Frequency)
The ‘% diff ’ column is the percentage difference
between Actual and Target frequencies computed as:
(actual - target)/target * 100%
11 — 3
Experiment 11: Controlling Time
Summer 2004/V0.2
B. Lab Activity
The sqwave.c program uses the PWM module to generate a square wave on the RC2/CCP1 output. The
program prompts the user to enter timer2 prescale and
PR2 values.
sqwave.c
Table 11–4: Square wave generation checkoff
Checkpoint
1.
Debugging/Comments
Use the sqwave.c program to check the values
you computed for Table
11-3.
Use a scope to monitor the output waveform on
pin ‘RC2/CCP1’. Use the frequency measurement capability of the scope to check if the output frequency matches the ‘actual frequency’
column in Table 11-3.
DEMONSTRATE THAT YOUR COMPUTED PRESCALE,
PR2 VALUES GIVE THE EXPECTED FREQUENCIES.
11 — 4
Summer 2004/V0.2
Experiment 11: Controlling Time
The ledpwm.c program outputs a square wave of a
fixed frequency, but allows dynamic update of the
duty cycle by reading the AN0 analog input. This 10bit value is used to set the value of the duty cycle.
Adjusting the potentiometer adjusts the duty cycle of
the square wave on the RC1/CCP1 pin.
ledpwm.c
Table 11–5: LED PWM Checkoff
Checkpoint
Comments/Debugging
1.
Verify the operation of
ledpwm.c on your PIC.
What happens to the
LED brightness as you
adjust the duty cycle via
the potentiometer?
Monitor the waveform generated on pin RC2/
CCP1 with the oscilloscope.
2.
Use a multimeter to measure the current through
the LED for various duty
cycles and complete
Table 11-6.
Table 11-16 requires two current measurements
for particular duty cycles. The two duty cycles,
based on your student ID, are: a) 0/1 5%/25%;
b) 2/3 10%/30%; c) 4/5/6 15%/35%; d) 7/8/9
20%/40%.
Also, measure current at the 85% duty cycle,
and at a duty cycle midway between the two
above.
Record your current measurements in Table 11–6.
Compute the expected current for the 3rd (halfway
between 1st and 2nd duty cycles) and the 4th (85%)
duty cycles. Ideally there is a linear relationship
between the current and duty cycle. Use the first two
measurements to compute a straight line slope that is
used to predict the currents for the last two duty
cycles.
11 — 5
Experiment 11: Controlling Time
Summer 2004/V0.2
Table 11–6: PWM Current Measurements
Duty Cycle (%)
Duty Cycle
(us)
Measured
Current (mA)
Expected
Current (mA)
% Diff
Pt1
N/A
N/A
Pt2
N/A
N/A
(Pt2+Pt1)/2
85%
SLOPE: ____________________ (record slope here)
WORK: (show work here)
SHOW AND DISCUSS THE RESULTS OF TABLE 11-6.
11 — 6
Summer 2004/V0.2
Experiment 11: Controlling Time
The sinegen.c program generates a sine wave using a
table lookup approach via the MAX517 DAC. The
program prompts the user to choose between a 16
entry or a 64 entry table. Timer2 is used to trigger an
interrupt that reads the next entry from the table. The
interrupt interval is set by a prescale value of 4, a
postscale value of 3, and the PR2 value that is set by
the A/D AN0 input. The sine wave period is:
sinegen.c
table_size * interrupt_interval
he 16-entry and 64-entry sine wave tables are in sinegen.h. The PR2 value is limited by sinegen.c to be
between 25 and 100.
Table 11–7: Arbitrary Waveform Generation
Checkpoint
1.
Comments/Debugging
Verify sinegen.c operation on
your PIC. Hook the audio jack
output to the powered speakers
of the PIC. Vary the period of the
sine wave via the potentiometer
and make primitive music.
Use the scope to monitor the output of the DAC.
2.
Note what happens for the 16table case when the frequency is
increased to near its maximum
value.
The interrupt interval becomes too small for the
DAC to be updated with the new table value
because of the I2C bus speed. This causes
waveform values to be skipped, degrading
waveform quality.
3.
Fill in the computations and measurements required in Table 11–
8.
If you do not hear a varying tone as you adjust
the sine wave period, check the audio jack connections.
11 — 7
Experiment 11: Controlling Time
Summer 2004/V0.2
Table 11–8: sinegen.c Measurements
Measurement
Expected
Measured
a. Min.TMR2 interrupt interval (PR2=25, PRE=4, POST=3), us
N/A
b. Max.TMR2 interrupt interval (PR2=100, PRE=4, POST=3), us
N/A
c. Min Sinewave Frequency, 16 entry (Hz)
d. Max Sinewave Frequency, 16 entry (Hz)
e. Min Sinewave Frequency, 64 entry (Hz)
f. Max Sinewave Frequency, 64 entry (Hz)
g. Measured I2C Bus Speed (KHz)
N/A
h. DAC update time (us)
i. Max sinewave frequency (16 entry) (Hz) without losing DAC
update values
Comments on sinegen.c
measurements
Values (a), (b) can be computed from the datasheet
formula for timer2 interrupt interval.
For (c) through (f), the period of the sinewave is the
interrupt interval times the number of table entries for
the sinewave; the frequency is the inverse of the
period.
For (h), compute the DAC update time by multiplying
the number of I2C bit times required for the DAC
update by the measured I2C bus speed. The measured
value can be obtained by using the scope on the I2C
bus.
For (i), the measured DAC update time determines the
minimum time interval for each new sinewave value.
The number of entries in the sinewave times this value
gives the minimum period of the sinewave that can be
reliability generated without skipping values. Sinewave values are skipped when the timer2 interrupt
interval becomes less than the DAC update time.
11 — 8
Summer 2004/V0.2
Experiment 11: Controlling Time
Table 11–9: Arbitrary Waveform Generation
Checkpoint
1.
Comments/Debugging
Modify sinegen.c to generate an
arbitrary waveform as described
in Table 11-8.
Following this table are detailed hints on how to
implement the arbitrary waveform generator.
Table 11-8 provides the details of the arbitrary waveform that you are required to generate. The waveform
is one or more sine wave cycles, followed by one or
more triangle wave cycles, followed by one or more
square wave cycles that are then repeated. A 1x period
is 64 time units; waveforms can have periods of 1x,
2x, or 0.5x. The waveform generated by sinegen.c has
a 1x period by this definition. The interrupt interval for
this program should be set in the same way as in sinegen.c. The triangle wave and square wave can also be
inverted; Figure 11-1 shows examples of inverted triangle waves and square waves. If one cycle of a waveform is inverted, all cycles are inverted.
Arbitrary Waveform Generation
Table 11–10: Waveform Assignments
If the last
digit of
your
student id
is:
Your waveform is
0
1 cyc sine, 2 cyc triangle (0.5x per), 1 cyc square (0.5x per)
1
2 cyc sine, 1 cyc triangle (2x per), 2 cyc square (0.5x per)
2
1 cyc sine, 1 cyc triangle (0.5x per), 1 cyc square (2x per)
3
2 cyc sine, 2 cyc triangle (2x per), 1 cyc square (2x per)
4
1 cyc sine, 2 cyc triangle (2x per, inverted), 1 cyc square (2x per)
5
1 cyc sine, 2 cyc triangle (2x per, inverted), 1 cyc square (0.5x per)
6
2 cyc sine, 1 cyc triangle (0.5x per), 2 cyc square (0.5 x per, inverted)
11 — 9
Experiment 11: Controlling Time
Summer 2004/V0.2
Table 11–10: Waveform Assignments
If the last
digit of
your
student id
is:
Your waveform is
7
1 cyc sine, 1 cyc triangle (0.5x per, inverted), 1 cyc square (0.5 x per,
inverted)
8
2 cyc sine, 2 cyc triangle (0.5x per, inverted), 1 cyc square (2x per)
9
1 cyc sine, 2 cyc triangle (0.5x per, inverted), 2 cyc square (2x per, inverted)
Because the sine wave always has a 1x period, use the
64-entry lookup table to generate this waveform. You
can use this same approach for square and triangle
waves, or you can compute the next value. The square
wave only has two possible values, 0xFF or 0x00, so it
is easy to compute its value. The triangle wave next
value is computed by adding or subtracting a constant
to the previous value. The constant is added when the
slope is rising; the value is subtracted when the slope
is falling. The constant added or subtracted depends on
the period; you can figure this out. Be careful of wraparound of the triangle wave value at its peak point - the
8-bit value will wrap to 0x00, and a 0xFF is required
for full scale output.
Note the first value of any waveform is always 0x80
(Vdd/2).
11 — 10
Summer 2004/V0.2
Experiment 11: Controlling Time
normal
inverted
normal
inverted
Figure 11.1 Examples of Normal and Inverted Waveforms
Your program must track the current cycle number and
the corresponding waveform to be generated. The tabmax variable in sinegen.c determines the period of a
waveform; this value can be changed from cycle to
cycle depending on the waveform being generated
(i.e., for 2x period tabmax = 128, for a 0.5x period tabmax = 32). Write separate subroutines for square wave
and triangle wave generation.
DEMONSTRATE YOUR ARBITRARY WAVEFORM GENERATION PROGRAM.
11 — 11
Experiment 11: Controlling Time
Summer 2004/V0.2
C. Report
1. Include source code listings of any C programs.
2. Include the values computed for Table 11–1.
3. Include the values computed for Table 11–6 including the slope computations. The accuracy of the
current prediction degrades for higher values of
duty cycle, why? (hint: look at Figure 16-16 in the
PIC datasheet).
4. Include the measured and computed values for
Table 11–8. Show your work for all computed values. Discuss reasons for any major discrepancies
between expected and measured values (in particular, address the DAC update time computation).
What limits the frequency of the sinewave generated by the table lookup method in sinegen.c? For a
sinewave with a fixed number of table entries, how
can this frequency be increased?
11 — 12
Summer 2004/V0.2
E x p e r i m e n t
Experiment 12: Time Measurement
1 2
Time Measurement
Precision time measurement is
important to many folks, like the
two-man bobsledding team who
missed the gold medal in the World
Cup by 0.06 seconds over 10 cumulative runs1. What makes such
magical disappointments possible?
Why the microprocessor, of course!
Read on, and find out how you too
can design a system that ruins
somebody’s day!
Summary
Use the PIC capture module to decode an infrared
pulse train via pulse width measurement.
1. No joke. FIBT Men’s 2-man bobsled, Altenberg, Germany 2002. 1st
place total over 10 runs: 1:53.04. 2nd place: 1.53.10. I think that I
would find a different sport.
12 — 1
Experiment 12: Time Measurement
Summer 2004/V0.2
A. Prelab Requirements
Table 12–1: Prelab Checkoff
Do This
Comments
1.
Connect a momentary switch to the
RC2/CCP1 input.
2.
The program swdet.c uses Timer1
and the Capture module to measure
the pulse width of a momentary
switch. Read this program and
understand its operation as you will
need to modify it to fulfill the lab
requirements.
Refer to the schematic
below.
Vdd
18F242
10K
RC2/CCP1
Figure 12.1 Momentary Switch to CCP1
12 — 2
Summer 2004/V0.2
Experiment 12: Time Measurement
B. Lab Activity
The swdet.c program uses the PIC’s capture module to
measure the low pulse width of a momentary switch.
The program captures the time of the falling edge, then
changes the capture mode to rising edge and captures
that time. The pulse width is the difference of these
two times. The swdet.c program only produces the correct calculation if timer1 overflows once or none. You
may have to push the button quickly to avoid multiple
timer1 overflows.
swdet.c
Falling edge,
capture time
as ‘A’
Table 12–2: swdet.c Checkoff
Checkpoint
Rising edge,
capture time
as ‘B’, width
is ‘B’ – ‘A’.
Debugging
1.
Verify the operation of
swdet.c on your PIC. The
‘timer tics’ that is printed
is the elapsed timer tics
between the edges; the
pulse width is the computed time in microseconds.
2.
Fill in the table below for
three button pushes.
Use a scope in single
trigger mode and capture the low pulse
width.
Table 12–3: Switch Pulse Width Results
Trial
Tics
Computed
Width
Measured
Width
% diff
1
2
3
12 — 3
Experiment 12: Time Measurement
Summer 2004/V0.2
.
Multiple Timer1 Overflows
Table 12–4: swdetnew.c Checkoff
Checkpoint
1.
2.
Debugging
Create a new version of swdet.c called
swdetnew.c. This new version must use a
scaling factor of 2 and print out the correct
time in microseconds even when timer1
has multiple overflows.
Use a scope in single trigger mode and
capture the low pulse width.
Only the time calculation must be
changed; no changes are required to the
interrupt code.
Fill in the table below for three button
pushes.
T
Table 12–5: Switch Pulse Width Results
Trial
Tics
Computed
Width
Measured
Width
% diff
1
2
3
DEMONSTRATE THE OPERATION OF SWDETNEW.C ON
YOUR PIC.
12 — 4
Summer 2004/V0.2
Experiment 12: Time Measurement
Place the IR receiver module from your parts kit on the
protoboard, and connect the OUT pin to the RC2/
CCP1 pin of the PIC.
IR Pulse Decoding
Connect Out to
pin RC2/CCP1 of
the PIC.
Bend carefully to
get out of the way
so can plug into
protoboard.
3 Vcc
1 2
Out Gnd
Obtain an IR universal remote from the TA to use as
an IR source. Program the remote with your assigned
code as found in Table 12–6. Monitor the OUT pin
with the oscilloscope in single capture mode (falling
edge), and use the VCR play button to trigger an output from the IR receiver module. The waveform
should look something like the diagram below:
# of bits depends
on IR remote
Start
‘0’
‘1’
Stop
The ‘0’ bit has a 50% duty cycle, while the ‘1’ bit has
a 75% duty cycle with a period that is 2x that of the ‘0’
bit. The period of the start bit, ‘1’ bit, ‘0’ bit, and number of bits in the frame depends on the IR remote control and function (VCR, TV, DVD, SAT). The
observed waveform may have different duty cycles for
12 — 5
Experiment 12: Time Measurement
Summer 2004/V0.2
‘1’, and ‘0’ depending on the remote control; always
assume that the ‘1’ value has the longer period.
Table 12–6: IR Remote Assignment
If the last digit of your
Student ID is...
Your IR Remote
Assignment is...
0 or 1
000
2 or 3
246
4 or 5
234
6 or 7
280
8 or 9
233
To program the remote with the assigned code,
press and hold the setup button until the LED
remains on. Release the setup button. Press and
release the VCR button. Enter the 3-digit code
above; the LED will blink for each keypress. At
this point, the remote is programmed with the
new code.
The PIC’s capture module can be used to capture the
number of timer1 counts between falling edges, and
thus determine the sequence of ‘1’s and ‘0’s in a
frame.
‘1’,’0’, Start periods
12 — 6
Complete Table 12–7 based on oscilloscope measurements. Determine a prescale value to use with the
timer1 module that will give capture deltas between
falling edges that can distinguish between a start, a ‘1’
bit, or a ‘0’ bit. Then use these values in a program that
decodes the first two bytes of a frame.
Summer 2004/V0.2
Experiment 12: Time Measurement
Table 12–7: Period Measurement
Bit Type
Measured
Period
Timer1
Ticks
Start Bit
‘0’ Bit
‘1’ Bit
Prescale
used:
Table 12–8: IR Decoding Checkoff
Checkpoint
1.
Using swdetnew.c as a starting point,
write a program called irdecode.c that
decodes the first two bytes of an IR
frame. Assume the bits are sent LSB
to MSB in each byte. Use the computed timer1 tick values in the table
above to help you detect the different
bits. Do not use these exact values;
use values that are somewhat less
than these and check the bit type
from longest to shortest.
Comments/Debugging
You should first check for a start
bit, then start checking for either
‘1’ or ‘0’ bits, right shifting the
received bit into a temporary
byte. Once 8 bits are received,
save this byte. Once two bytes
are received, print the values of
the two bytes and verify they are
correct by decoding observed
waveform.
The following are suggestions on how to write your
irdetect code; there are MANY other code variations
that can accomplish this task.
Hints for IR Decoding
While the swdet/swdetnew programs provide a good
starting point, there are important differences between
swdet/swsdetnew and idecode.
The swdet/swdetnew code measured time between a
falling edge and a rising edge; the irdecode code must
measure time between successive falling edges. This
means that you should not change the compare mode
12 — 7
Experiment 12: Time Measurement
Summer 2004/V0.2
once you have set it to falling edge triggered (the
edge_type variable is not needed).
The swdetnew code only made one measurement; irdecode must make several time measurements, where
each measurement is used to distinguish a one or zero
bit, and these bits are accumulated into two bytes to
provide the decoded value.
All of the time measurement and bit accumulation
work can be done by the interrupt service routine
(ISR). Because several measurements are made, there
is a temptation to put a loop into the ISR to accumulate
the 16 bits needed for the two decoded bytes. However, an ISR cannot have a loop in it as the ISR must
exit so that another interrupt can occur.
One or more variables must be used to keep track of
what happens between different triggerings of the
interrupt service routine. This is a finite state machine
approach to programming, and typically a temporary
variable called state is used to keep track of what the
ISR should do on each interrupt trigger.
Initially, set state to IDLE (you can assign any numbering scheme you wish for these states; here names
are used for states for clarity).
IDLE: Identify if the IR output has been idle; this can
be done by counting timer1 overflows; once a particular count has been exceeded, change the state to
START1. Checking for idle is important as in this way
you can clearly identify when the start bit occurs.
START1: A capture interrupt in the START1 state is
the falling edge of the start bit; change the state to
START2.
START2: A capture interrupt in the START1 state is
the falling edge of the first data bit; remember this capture time and change the state to DATA.
12 — 8
Summer 2004/V0.2
Experiment 12: Time Measurement
DATA: Each capture interrupt in this state is the falling
edge of a data bit. The time between the current capture and last capture is the pulse width of the last data
bit. Determine if a ‘1’ or ‘0’ occurred, and shift these
bits into a temporary variable. Once 8 bits have been
captured, record this as the first byte. Record 8 more
bits for the second data byte (a total of 16 bits has been
captured). Set a flag called PRINT that will cause the
main() routine to print out the bytes and set the state to
IDLE to begin looking for an idle condition again. You
will need to use a temporary variable to track the number of bits in a byte that has been captured, and another
variable that identifies which byte is being used for
recording the bits.
The above code is placed in the interrupt service routine. The main() routine does configuration and
enables interrupts, then enters an infinite loop that
waits for PRINT to become a ‘1’, prints the two bytes
that were received, resets PRINT to ‘0’, and loops
back. Do NOT put any print statements in the ISR.
Again, there are other ways to write irdetect. For
example some of the above code could be placed in
main(); the division of labor between the ISR and
main() is a user preference. The only limitation on the
amount of code in the ISR is that the execution time of
the ISR must be shorter than the expected interrupt
interval time so that interrupt events are not missed.
DEMONSTRATE YOUR IR DECODING PROGRAM. CAPTURE A FRAME USING THE OSCILLOSCOPE AND VERIFY THAT THE DECODED BYTES MATCH THE
OBSERVED BITSTREAM.
12 — 9
Experiment 12: Time Measurement
Summer 2004/V0.2
C. Report
1. Include source code listings of any C programs.
2. Include the results of Table 12–3 and Table 12–7.
12 — 10
Summer 2004/V0.2
E x p e r i m e n t
Experiment 13: The PIC Listens and Speaks
1 3
The PIC Listens and Speaks
This is it, the last lab! Hurrah! After
this you will have learned everything
there is to know about µPs and will
never have to suffer from µP brain
strain again.....uh, sorry, no. At some
later point in your career, you will be
faced with µP WTH911 with 101
onboard modules including the latest
serial standard KITSYNC. Hopefully,
these lab experiences will help you to
read the datasheets, strain your
brain, and make sense of it. In other
words, the fun with learning about µPs
has just begun; welcome to life long
learning!
Summary
Have the PIC record audio to serial EEPROM and then
play it back, using different sampling rates.
13 — 1
Experiment 13: The PIC Listens and Speaks
Summer 2004/V0.2
A. PreLab Requirements
Table 13–1: Prelab Checkoff
Do This
Comments
1.
Wire all connections shown in the
schematic. You will not receive
prelab credit unless your protoboard
is fully wired before lab. Note that
the serial EEPROM is not shown,
but it is required as well for storing
the digitized audio.
The LM386 is an 8-pin DIP made by
National Semiconductor. It provides
a fixed analog gain of 20 with the
output biased to 1/2 the power supply. No external components are
required.
2.
Read the notes below on audio sampling, then fill in the tables regarding
sample rate computations.
A simple spreadsheet would help in
these calculations.
3.
The audio.c file attached to the lab
will sample the AN0 input at a fixed
rate and store the values in
EEPROM. Read and understand this
program as playback functionality
must be added to this program.
Change the ROM, DAC define statements is audio.c to match the previously assigned I2C addresses for
these devices.
DAC
DIP Switch
Maxim 517
Open for record
Closed for playback
OUT0
Audio mini
jack
I2C
bus
18F242
RA0/AN0
LM386
Vout
+
-
use volume control on PC to
adjust audio signal magnitude
Figure 13.1 Audio Sampling Schematic
13 — 2
Summer 2004/V0.2
Experiment 13: The PIC Listens and Speaks
The audio.c file attached to this lab uses timer2 to generate an interrupt at a fixed interval to sample the A/D
input and store the result to EEPROM. The same double-buffered page write approach as used previously to
capture serial data is used here. Two 64-byte buffers
are used; while one buffer is being written to
EEPROM, the other buffer is being used to capture
data from the A/D.
Audio Sampling
The sampling interval is the time interval between
reads of the A/D. The inverse of the sampling interval
is the sampling frequency. The audio playback quality
degrades if the sampling frequency is too low. A sampling frequency of 8 KHz (or sampling interval of 125
µs) is considered adequate for non-music audio. For
music, a sampling rate of 14.4 KHz is commonly used.
Audio samples are typically compressed in some manner to reduce storage requirements. The audio.c program only saves the most significant 8 bits from the A/
D value and does no compression when saving to
EEPROM.
Playback must be at the same sampling rate as used
during record. For each sample, the value is read from
EEPROM, then written to the DAC. Because reads are
from sequential locations, a current address read is
used each time to fetch a byte from EEPROM. This
requires sending one command byte and then reading
the return byte from the EEPROM; the following read
is from the next sequential address. Read more about a
current address read in the EEPROM datasheet.
Complete Table 13–2 for playback and Table 13–3 for
record to determine which is the critical path in limiting the sampling rate of the audio signal. For instruction overhead calculation, assume a 14.7456 MHz
13 — 3
Experiment 13: The PIC Listens and Speaks
Summer 2004/V0.2
clock with each instruction taking 4 clock cycles to
execute. Also assume a 400 KHz I2C bus speed.
Table 13–2: Playback Calculations
Category
Time/Frequency
a) DAC Write Time per sample
b) EEPROM read time per sample
c) Instruction overhead time per sample (assume 100 instructions)
d) Total sample time (a+b+c)
e) Max playback rate (1/d)
Table 13–3: Record Calculations
Category
Time/Frequency
a) I2C transfer time for page write
b) Page write completion time
0.005
c) Instruction overhead per sample
(assume 40 instructions)
d) Total Write time (a + b + 64* c)
e) Sample interval (d/ 64)
f) Maximum sampling frequency (1/e)
The instruction overhead for record is less than playback because it is principally the overhead of the interrupt routine whose only task is to store the A/D value
in a buffer.
IN THE PRELAB CHECKOFF, DISCUSS WHICH FUNCTION, RECORD OR PLAYBACK, IS THE LIMITING FACTOR FOR SAMPLE FREQUENCY.
13 — 4
Summer 2004/V0.2
Experiment 13: The PIC Listens and Speaks
B. Lab Activity
Table 13–4: Playback Checkoff
Checkpoint
1.
2.
Comments/Debugging
Compile the audio.c program and
verify that the connections are correct for audio sampling. Do this by
using an audio cable to connect the
line out from the PC to your audio
plug. Use Windows Media Player to
play any of the attached WAV files.
Chose the calibrate option to determine if there is sufficient voltage
variation on the AN0 input (also use
the oscilloscope to view this waveform).
Adjust the POT to change the amplitude of the input signal seen by the
LM386 input; this changes the range
of the input signal seen at the AN0
input of the PIC.
Modify the audio.c to add a playback
option. Test your playback first at 4
KHz, then try to achieve an 8 KHz
playback. Also test at 2 KHz.
Read the hints below on how to
achieve an 8 KHz playback rate.
The TA will provide the audio cable
and mini-jack connector.
Note how the audio quality improves
as the sampling rate increases.
The flowchart on the next page provides a basic idea
of what is needed for playback. All of this work is
done outside of the interrupt service routine, whose
only job during playback is to set a flag indicating that
an interrupt has occurred and that a sample should be
read.
Implementing Playback
To set the EEPROM address to zero, a write command
to location 0 is issued. However, instead of providing
write data to the EEPROM after the address, a stop
condition (i2c_stop() function) is issued. This aborts
the write operation, but leaves the internal address
counter pointing at location 0. Read more about this in
the EEPROM datasheet.
The interrupt_flag variable is set by the interrupt service routine to indicate that an interrupt has occurred.
This is not the timer2 interrupt flag; the clearing of this
bit is already handled by the interrupt service routine.
13 — 5
Experiment 13: The PIC Listens and Speaks
To reach an 8 KHz sampling rate, the I2C bus must be
run above the 400 KHz maximum bus rate. More
importantly, the playback loop must be written as efficiently as possible. To improve execution time, flatten all subroutine calls. This means that instead of
performing a call to i2c_GetByte(), copy the code from
i2c_GetByte() directly into the loop to save the subroutine call and return overhead. Also, most of the i2c
functions include a call to the i2c_idle function. This is
really not necessary in this case as the PIC is the only
master on the bus. Removing these calls saves a substantial amount of execution time.
Initialize
EEPROM
address to 0
Enable tmr2
interrupt
Read byte from
EEPROM
Wait for interrupt
0
Interrupt_flag?
interrupt_flag=0
Write byte to
DAC
Summer 2004/V0.2
Note that the playback loop never exits; when the read
reaches the last location in the EEPROM the internal
address counter rolls over to 0. The playback continually loops through the entire EEPROM contents with
the only exit being via a RESET condition.
Place an overrun check before the ‘wait for interrupt’
box to determine if the interrupt_flag is already a ‘1’.
If this is true, then the playback loop is too slow for the
current sampling rate - write a ‘!’ to the serial port in
this case to provide visual evidence of overrun.
DEMONSTRATE YOUR AUDIO PLAYBACK AT THE
FASTEST PLAYBACK THAT YOU WERE ABLE TO
ACHIEVE
(8 KHZ IS AS FAST AS YOU NEED TO GO).
ALSO DEMONSTRATE A PLAYBACK AT A SPEED THAT
SHOWS THAT YOUR OVERRUN CHECK IS WORKING.
13 — 6
Summer 2004/V0.2
Experiment 13: The PIC Listens and Speaks
C. Report
1. Include source code listings of any C programs.
2. Include the results from Table 13–2 and Table 13–
3.
3. What is needed in order to reach a record and playback speed of 14.4 KHz?
13 — 7
Experiment 13: The PIC Listens and Speaks
13 — 8
Summer 2004/V0.2
Summer 2004/V0.2
A p p e n d i x
Appendix A: Prototyping Hints
A
Prototyping Hints
Read this for hints on building
stuff. And boy, will you ever be
busy building stuff!!! Breaking
stuff, also, most probably. A favorite pastime of students is to connect VDD directly to GND. But this
sorta does bad things to chips
like...BLOW THEM UP!!! So read the
hints in here and save the life of a
chip, OK?
A—1
Appendix A: Prototyping Hints
Summer 2004/V0.2
A. Protoboard and Parts
Protoboard Layout
Above is a sample protoboard layout for the PIC processor and most of the components used in the lab
exercises. DO NOT use this picture as schematic - it
is not a substitute for datasheets that provide the pinout
of each component. The above component placement
can be used for the entire semester. Of course, this is
only a suggested layout; it does not have to be followed. Some students in the past have ignored the
above picture and placed components semi-randomly,
only to find they have to completely rewire their protoboard halfway through the hardware labs because they
don’t have enough room. So avoid this, and be careful
in your component placement and neat in your wiring.
The above picture has more components on it than
what is needed for the initial hardware labs. Either
place all of the components at once or place them as
required by the lab exercises.
The schematics in this lab manual do not have pin
numbers on them. There are two reasons for this:
1. It is important for you to learn how to read
datasheets to determine pin numbers and device
capability.
2. If pin numbers were placed in the diagrams, then
inevitably one or two would be wrong, causing you
to become angry. And who needs that? Be happy,
read the datasheets!
In this appendix, pinout information is provided for
some of the simpler components. For the more complex components (PIC, DAC, EEPROM, etc.) refer to
the datasheets linked to the lab website. In reading
some of the remaining comments about components,
understand that over time the components in the parts
kit may change over time and those changes may or
A—2
Summer 2004/V0.2
Appendix A: Prototyping Hints
may not be reflected in the current version of this document. How do you know if a component has
changed? Well, if the component described here has 4
pins, and the component in your part kit has 50 pins,
then the component has changed. Look for subtle differences like that, and you will be A-OK.
This is the socket for the plug from the wall transformer. It has three pins: bottom, side, and back. The
bottom pin is the GROUND pin and should go to the '' protoboard power rail. The back pin is the +V supply
voltage (9V or 12V depending on the transformer), it
should be connected to a pin on the power switch. The
side pin is left unconnected.
Power Connector
DO NOT PLUG THIS CONNECTOR INTO THE
BOARD. The power connector does not plug well into
a protoboard, and will easily pop out if jostled. You
MUST have a solid power connection to your protoboard.
If your power connector has eyelets, then solder wires
from your wiring kit onto each eyelet, and use these to
provide power to your board. If your power connector
does not have eyelets, then wirewrap a length of wire
to each pin. For each wirewrap connection, add a dab
of solder to make sure these are firmly connected. You
can connect the other end of the wirewrap wire to a
wirewrap header on your board, or solder them to a
wire from your wirewrap kit and then plug the wire
into the board.
The 7805 is used to provide a regulated + 5V output.
In the protoboard picture, the right pin is connected to
the output of the power switch, and the left pin is the
+5V output. Note that in the picture the labeling on the
7805 is facing away from the user. The middle pin is
ground and should be connected to the '-' protoboard
ground rail. After connecting the wall transformer,
power switch, and voltage regulator for the first time,
Voltage Regulator (7805)
A—3
Appendix A: Prototyping Hints
Summer 2004/V0.2
use a multimeter to verify that the 7805 is providing
+5 V before plugging in any other components.
PCB Fuse
The parts kit contains two fast-blow PCB fuses. Use
one of these between the voltage regulator and the
+5V power to the rest of the protoboard. Be careful,
even momentary shorts caused by touching VDD and
GND together can blow the fuse. If the fuse is not
used, then shorting power and ground will cause
excessive current flow from the wall transformer,
causing it to overheat and eventual permanent damage.
When using the fuse, if your LED power light does not
come on when the power is applied, then use the ohmmeter to check the resistance of the fuse (remove the
fuse from the protoboard before checking the resistance). If the fuse does not have zero or very low resistance, then it has blown and must be replaced.
Resistor SIP Packages
The parts kit contains two resistor SIP packages (470
ohm and 10K ohm) whose pinout is shown below. The
470 ohm resistors are used for current limiting LEDs.
The 10K ohm resistors are used as pull-ups for
switches.
Figure A.1 SIP Package, Isolated Resistors
Capacitors (1.0 µF/0.1
µF)
A—4
The parts kit contains 1.0 µF tantalum capacitors if
your kit has a MAX232, or 0.1 µF if your kit has a
MAX202. These capacitors have clearly marked +
(positive supply), - (ground) terminals. Place a capacitor between the Vdd and Vss pins on the PIC - this
Summer 2004/V0.2
Appendix A: Prototyping Hints
helps protect the PIC from noise on the power supply.
The capacitors are also needed for the MAX232/202
chip used in the RS-232 serial interface labs.
An LED is useful as a visual indicator for a digital output. The diagram below shows how to identify the
cathode/anode terminals on a LED. The diagram also
shows the two ways to drive an LED from a digital
output.
Light Emitting Diodes
(LEDs)
+5V
470 ohm
Low True output
Anode (long lead)
PIC
output
=0, LED on
High True output
=1, LED off
PIC
output
=1, LED on
Cathode (short
lead)
=0, LED off
470 ohm
Figure A.2 LED Usage
Connect one LED using a 470 ohm resistor so that it
turns on when power is applied. This provides a warm
and fuzzy feeling that power is on when trying to figure out why the circuit is not working.
Power LED
A—5
Appendix A: Prototyping Hints
Summer 2004/V0.2
Power Switch
There is no power switch with the wall transformer in
the power kit. Remove power by unplugging the wall
transformer from the wall, or from the power jack on
the protoboard. There is also a slide switch in the parts
kit than can be used as an on/off power switch as
shown in the protoboard picture. Do not plug/unplug
any chips (especially the PIC) when power is applied the device may be damaged if it is momentarily placed
in the wrong protoboard location.
Momentary Pushbutton
Switches
The parts kit contains one or more momentary pushbutton switches (closed on push). The pinouts on these
switches are not standard, so use an ohmmeter to
determine which two pins are shorted (have zero resistance) when the button is pushed. The diagram below
shows how to connect the pushbutton to a digital
input.
+5V
10K
ohm
PIC
input
Input read as ‘0’
when switch is
pressed, read as ‘1’
otherwise.
Push button,
momentary
closure when
pushed.
Figure A.3 Pushbutton Usage
7.3828 MHz Crystal
A—6
A crystal and two 15 pF capacitors are used for the
oscillator option. The crystal is easily identifiable as it
Summer 2004/V0.2
Appendix A: Prototyping Hints
has a cylindrical metal casing with two pins. Because
the crystal sticks up from the protoboard it is easy to
knock it askew when adding wires; be careful.
A potentiometer (i.e, 'pot') is a variable resistor; they
have three pins as shown below. On a three pin package, the middle pin is the 'wiper' lead as shown. To
produce a variable voltage on the wiper pin, connect
pin 1 to VDD and pin 3 to GND (or vice-versa).
Adjusting the potentiometer will change the resistance, changing the voltage present on pin 2. The
potentiometer will be used to provide a variable voltage whose value can be measured using the PIC onchip analog-to-digital converter. The potentiometer in
your parts kit has two back pins that are close together;
these are the pins that should be connected to VDD
and GND. The other two pins are spaced widely apart;
either of these can serve as the wiper pin. Use wire
wrap wires or soldered wires to provide a reliable connection from the potentiometer to the protoboard. The
potentiometer in the pictures uses wire wrap wires
from the pot to the 5 pin header plugged into the protoboard.
Potentiometers
Figure A.4 Potentiometer
A—7
Appendix A: Prototyping Hints
Summer 2004/V0.2
Audio Connector
The audio mini-jack is a mono jack with three pins.
Looking into the connector, the middle pin is ground,
and the left pin is the signal pin.
Wire Wrapping
Wire wrapping is quickly becoming a lost art. Soon,
only Jedi Masters will know the proper technique for
wielding a wire wrap tool. Wire wrap is useful for creating reliable, non-solder connections. It is used in this
lab to interface the protoboard to external connectors
(DB9, modular jack) that cannot directly plug into the
protoboard. In these experiments, the total number of
connections made via wire wrap can be as little as 3, or
at most 11, so do not worry about spending hours and
hours becoming a wire wrap guru. The TA can demonstrate everything there is to know about wire wrapping
in 30 seconds; use the description below for reference.
Wrap end
Unwrap end
Wire stripper
Wire wrap creates
connections that look
like this.
The picture above shows the wire wrap tool available
from the TA; this tool wraps 30 AWG wire. The steps
for creating a wire wrap connection between two posts
are:
1. Cut a section of wire the appropriate length. Leave
plenty of slack, length is not important in these
connections. Use scissors, pliers, or even the strip
tool on the wire wrap tool to cut the wire. Do not
use your teeth; your dentist would not approve.
2. Use the wire stripper on the tool and strip about 1/2
inch from each end.
3. Look into the wrap end of the tool. Find the hole in
the center; this fits over the post. Look more
closely, and find the small second hole near the side
corresponding to the slit that runs along the side of
A—8
Summer 2004/V0.2
Appendix A: Prototyping Hints
wrapping end. Insert the bare end of the wire into
this small second hole; the bare wire should be visible along the side slit. The wire cannot be inserted
past where the insulation has been stripped.
4. Place the wire wrap tool over a post, and turn in a
clockwise direction until all of the bare wire has
been wrapped around the post (for the clock-challenged, clockwise == righty-tighty).
5. Repeat 3,4 for the second post.
If a mistake is made, insert the unwrap end over the
post and turn in a counter-clockwise direction to
unwrap.
Wire wrap connections are nearly foolproof. One
potential problem occurs if all of the bare wire is not
wrapped around the post. For the unlucky, this
unwrapped bare portion of the wire shorts against an
adjacent post on the connector creating a debugging
headache.
If your protoboard is old, chips and devices may have
trouble staying in; they may pop out over time or be
loose even after being seated in the board.
Get a decent protoboard!
Here is a piece of advice -- if you have an old protoboard which exhibits this problem, GET A NEW
BOARD!!!!!! Save the TAs, and the poor students
who have to work near you in lab the agony hearing
you cry like a baby in frustration because you CANNOT GET THE BOARD TO WORK. You will have
problems enough with a good protoboard; having a
flakey protoboard makes finishing the hardware exercises a near impossibility, and will have you questioning the wisdom of majoring in EE, CPE or CS in the
first place as it forces you to take this unbelievably
frustrating course.
A—9
Appendix A: Prototyping Hints
Summer 2004/V0.2
Your PIC system will have to live through several
hardware labs, so the components will have to stay on
the board between labs. A tackle box or sewing kit box
makes a good container for carrying your board and
other components.
Get a multimeter!
A — 10
There are multimeter at each station in the lab, but it is
handy to have an extra multimeter that is dedicated to
monitoring current -- that way you can easily see if a
short has occurred. A small multimeter is fairly inexpensive from electronics stores and useful around the
house (well, at least it is useful around my house with
its pre-colonial wiring). You will find it useful in other
electrical engineering labs as well, so go ahead and
invest in one.
Summer 2004/V0.2
Appendix A: Prototyping Hints
B. Debugging
Here is a common situation observed in lab: a student
stares intently at their board, trying to figure out what
is wrong. Meanwhile, the scope and multimeter sit
unused. Unless you possess X-ray vision, staring at a
board does not do much help. Repeat after me three
times “I SOLEMLY PLEDGE TO USE THE
INSTRUMENTATION TO DEBUG MY PROBLEMS -- IN THIS WAY I WILL NOT DRIVE THE
POOR TA CRAZY.” Read the next appendix and
become familiar with a scope and multimeter; a little
time spent becoming familiar with their operation will
save you literally hours of debugging time later.
When debugging a problem, follow a step by step procedure and eliminate potential problems sources in a
methodical way. Again, this will save time, which is
always good! The following debug checklists can be
used to help locate common problems.
1. Used multimeter to check VDD to PIC? (yes/no)
2. Are all VSS pins (yes, there are more than one!) on
the PIC are connected to ground? (yes/no)
3. Used scope to see if crystal is working (yes/no).
4. Used scope to ensure reset line works (yes/no).
5. Checked PIC with older test program (like ledflash)
(yes/no).
6. Checked PIC in TA board to see if board problem?
(yes/no).
My board used to work
and now it doesn’t!
To solve this problem, do not use a fuse until the short
is located, and use a multimeter to monitor the current
flow.
My fuse keeps blowing,
my board used to work,
help!
1. Disconnect one half of the protoboard from the
other half and determine which half the problem is
in. Only connect power for a brief period of time to
see if short still exists.
A — 11
Appendix A: Prototyping Hints
Summer 2004/V0.2
2. Remove all ICs from problem half of board and see
if short is fixed.
3. If short still exists, remove any capacitors.
4. If short still exists, then remove any switches.
5. If short still exists, then remove any LEDs.
6. If short still exists, then it must be a direct wiring
connection between Vdd/GND.
My RS232 interface does
not work and/or serial
bootloader does not
work.
The following steps can be used assuming your PIC is
programed with the serial bootloader firmware -- use
the serial bootloader Windows client and attempt to
program your PIC. After pressing ‘program’ from the
bootloader window on the PIC, the PC client sends a
character periodically to the PIC in an attempt to connect to the PIC bootloader firmware in the PIC. This
gives you serial data to look for with the scope.
1. Is MAX202 Vdd/GND connected? (yes/no)
2. Is MAX202 is producing +/- 10V? (yes/no)
3. Remove power from the PIC, press ‘Program’ on
the bootloader Windows client interface, turn
power on to the PIC.
4. Is character from PC arriving at DB9 TX pin? (yes/
no)
5. Is character from PC arriving at MAX202 Rin pin?
(yes/no)
6. Is character from PC arriving at MAX202 Rout
pin? (yes/no)
7. Is character from PC arriving at PIC RX pin? (yes/
no)
8. Is a character from PIC seen at PIC TX pin? (yes/
no) If YES, then follow the remaining steps, the
bootloader firmware is attempt to send bytes back
to the PC.
9. Is character from PIC reaching the MAX202 TIN
pin? (yes/no)
10. Is character from PIC reaching the MAX202
TOUT pin? (yes/no)
A — 12
Summer 2004/V0.2
Appendix A: Prototyping Hints
11.Is character from PIC reaching the DB9 TX pin?
(yes/no)? (If yes, try a bootloader on a different
PC).
If you did not see a character from the PIC at step 8,
then get the TA to reprogram your PIC with the bootloader firmware. Verify your PIC works in the TA
board, and download the sercomm program and verify
sercomm works in the TA board. If your PIC still does
not work in your board, then verify the PIC to DB9
link use steps 8-11 above. Be sure that Hyperterm is
configured with no flow control.
1. Verified both SCL and SDA have VDD via pullups
when idle. (yes/no)
2. Do you have SCL/SDA swapped? (SCL is the
CLOCK!) (yes/no)
3. Verified transmission by PIC on both SCL/SDA
(yes/no)
4. Verified I2C device address in your program (yes/
no)
5. Verified I2C device address on A1/A0 pins of
EEPROM/DAC (yes/no)
6. Is I2C Device (EEPROM/DAC) sending an ACK
for each byte transmission? (yes/no)?
My I2C interface does not
work.
1. Check the reset pin and ensure that a 10K PULLUP
is on this pin, with the reset switch configured to
pull the MCLR line low when pressed.
2. Ensure that the configuration bits have Low Voltage Programming (LVP) DISABLED. If LVP is
enabled, then pin RB5 must be grounded. You can
ground RB5 and see if the problem disappears.
My PIC seems to be
spontaneously resetting?!
A — 13
Appendix A: Prototyping Hints
Summer 2004/V0.2
3. Program the PIC with the pertest.c sample code
and see if it is a power-on reset or watchdog timer
reset, or neither.
My A/D input does not
work?
A — 14
1. Used a multimeter to check A/D input voltage variation (yes/no).
2. Verified that analog input connected to correct A/D
input (yes/no).
3. Verified that PORTA is configured for analog input
(yes/no).
4. Used print statement to print individual A/D result
bytes (yes/no).
Summer 2004/V0.2
A p p e n d i x
Appendix B: Instrumentation
B
Instrumentation
Instead of screaming at your protoboard during a debugging session, try using an oscilloscope -- it
might be more productive!
A. TDS 210 Oscilloscope
The picture above shows the TDS 210 scope used in
the lab. The numbers on the diagram are used to
explain the scope functionality.
1. Turn on the oscilloscope via the power button on
the top left.
2. Hook the Channel 1 oscilloscope probe (found
below button #14) to the test output that is under
button #11. Be sure to connect the ground input of
the probe (the alligator clip) to the ground of the
Displaying a continuous
waveform
B—1
Appendix B: Instrumentation
Summer 2004/V0.2
test output. The test output provides a continuous 1
KHz square wave output that is 5 V peak-to-peak.
3. Press the AUTOSET button (button #27) on the
oscilloscope. The AUTOSET button automatically
adjusts the display settings of the oscilloscope to
provide a readable waveform. After a few seconds,
a square wave waveform should be visible on the
screen. If no waveform is visible, press the CH1
Menu buttons (button #16) a couple of times until
the waveform appears, then press the AUTOSET
button again. Pressing the Ch1 Menu and Ch2
Menu buttons will show or hide the corresponding
waveforms.
Voltage/Time Scaling
4. Turn the Channel 1 VOLTS/DIV knob (#14) a few
times. This knob changes the scale factor for viewing the channel 1 waveform. As the knob is turned,
notice how the waveform is scaled taller or shorter
accordingly. Knob #15 does the same for the channel 2 waveform.
5. Turn the SEC/DIV knob (knob #21). This changes
the time-base for the waveform. As the seconds per
division is increased, the waveform is 'compressed',
and vice versa. Twist the SEC/DIV knob clockwise
to reduce the time per division, expanding the
waveform. Adjust the time-base so that approximately two cycles of the waveform are displayed.
Measure Function
6. Press the measure button (#2). This displays the
measure menu choices on buttons #7 through #11.
7. Press #7 until Source is highlighted. This changes
the source of a measurement for buttons #8 through
#11.
8. Press button #8 a couple times; notice that this
switches measurement choices between channels 1
and 2. Press button #8 until CH1 is highlighted, and
do the same for buttons #9, #10.
B—2
Summer 2004/V0.2
Appendix B: Instrumentation
9. Now press #7 to change from Source to Type. This
changes the type of measurement for buttons #8
through #11.
10. Press #8 until the Pk-Pk measurement is selected.
Notice that the peak-to-peak voltage value of the
waveform is displayed.
11. Press #9 until the Period measurement is selected.
Note that the period of the waveform is now
selected.
12. Press #10 until the Freq measurement is selected.
Note that the frequency of the waveform is now
selected.
13. Press the cursor button (#5). This changes buttons
#7 through #11 to the cursor menu.
14. Press button #7 until Voltage is selected. This button selects Voltage, Time or Off for cursor mode.
15. Press button #8 until CH1 is selected as the source.
16. Use knobs #12 and #13 to adjust the positions of
cursors #1 and #2 respectively. Note how the delta
value opposite button #9 displays the voltage difference between the two cursors.
17. Press button #8 until Time is selected. Note that
this changes the cursors from horizontal lines to
vertical lines.
18. Adjust the cursors to measure the high pulse width
of the square wave waveform. The delta value
opposite button #9 displays the time difference
between the two cursors.
Cursor Function, measuring voltage difference, pulse width
Button #23 controls the trigger menu. The trigger
function determines when the scope captures a particular waveform. The capture can be triggered off the
waveform on CH1, CH2 or an external input. The trigger can be tied to a particular edge (rising or falling)
and a particular voltage point. In normal trigger
mode, the display is updated each time the trigger con-
Trigger Function, continuous or single shot capture
B—3
Appendix B: Instrumentation
Summer 2004/V0.2
dition is met. In single trigger mode, the display is
updated with the first waveform that trips the trigger.
19. Press button #23 to display the trigger menu
choices on buttons #7 through #11.
20. Use button #7 to select Edge as the trigger mode;
this is the mode that is normally used.
21. Use button #11 to select Normal trigger mode.
22. Use button #8 to select between Rising and Falling
edge triggered. Note how the waveform shifts one
half clock cycle each time you change edges, with
the active edge being in center of the screen.
23. Use the horizontal position knob (#19) to change
the horizontal location of the trigger point. This is
useful in observing complex waveforms where the
trigger point is moved to the left edge of the screen
in order to use all of the screen for viewing the captured waveform.
24. Use the trigger level knob (#22) to adjust the voltage level of the trigger point. Typically, this level is
set midway between the peak-to-peak point of the
waveform.
25. Use button #11 to select Single trigger mode. Note
that the trigger status at the stop of the screen says
‘Stop’ because the trigger has been tripped, and the
waveform captured. In a repeating waveform like a
square wave, this mode is not very useful. However, this mode proves vital to capturing one-time
events such as data being sent over a serial line. To
capture another event after the trigger has been
tripped, use button #11 to select Normal, then back
to Single again (this procedure clears the waveform
from the screen). The Run/Stop button (#29) can
also be used by pressing it once so that Run appears
at the top of screen, arming the trigger capture.
AC vs. DC Coupling
B—4
In a couple of the menus, such as the trigger and the
channel menus, a choice between AC and DC cou-
Summer 2004/V0.2
Appendix B: Instrumentation
pling is given. AC coupling removes any DC value
from the waveform and thus the waveform is displayed with the 0 V reference midway between the
waveform’s peak-to-peak value. DC coupling displays the waveform referenced to ground. The Ground
choice in the coupling menu displays the position of
the ground reference.
B. Multimeter
A multimeter is used to measure voltage, resistance,
and current. In this lab, the multimeter is principally
used to measure resistance and current since the scope
can be used to measure voltage. The multimeter type
varies between lab stations, but all of them have the
same general functionality.
The black lead should be plugged into the Common or
ground input, with the red lead into the V/Ω input. To
measure the voltage of a pin on a protoboard, connect
the black lead to the ground of the protoboard, the red
lead to the pin that is the voltage measurement target.
Use the DC(V) button on the multimeter to select voltage measurement. Use the Range buttons to select the
voltage range. A value of 20 means that 20 V is the
maximum that can be measured. Choosing smaller
ranges provides more digits to the right of the decimal
point in the display.
Measuring Voltage
Use the OHMs button (or KΩ) to select resistance
measurement. The range values are in Kohms (1K =
1000 ohms). The display should blink indicating an
open circuit (infinite resistance). Touch the leads
together to short them, and the display should read a
value near 0 (a short is zero resistance). Attach the
leads across the pins of the device that is the resistance
measurement target. The device should be out of the
protoboard; do not try to measure resistance when the
device is plugged into the protoboard. A good test
Measuring Resistance
B—5
Appendix B: Instrumentation
Summer 2004/V0.2
case is a switch, either push button or slide switch. In
the open position the resistance across the switch terminals should be infinite, in the closed position the
resistance should be zero (a short).
Measuring Current
To measure current, plug the red lead into the ma input
of the multimeter, and select the DC (mA) function.
The range values refers to milliampere (1 mA = 0.001
A). To measure current flowing through a device, the
multimeter is connected in series with the device. The
figure below shows how to measure the current consumption of a PIC.
+5V
multimeter
DC mA
Common
PIC
Vdd
Vss
Figure B.1 Current Measurement with multimeter
To measure total current through your board, place the
multimeter in series your power switch to the 7805
voltage regulator.
B—6
Download