The Design Cycle
real world problem I encountered and solved using serial
port debugging techniques.
Bait and Switch ...
Writing for Nuts & Volts is great in that I have the
opportunity to touch, feel, and tell you about all of the
latest and greatest microcontrollers and all of the stuff
that supports them. However, there are some gotchas
that come with the territory. Sometimes, things just don’t
work as designed.
For instance, Listing 2 is a simple firmware
implementation of an AND gate. Port B pins 0 and 1
are the inputs to the AND gate with Port B pin 2 acting
as the logical output of the AND gate. Port B is read
continually (logic_levels_in = input_b();) and the lower
two bits (the AND gate inputs) are isolated by logically
ANDing the Port B input with a bit mask of 0x03
(logic_levels_in &= 0x03;). Physical AND gate logic
works as follows:
The input logic levels represented by Input 1 and
Input 2 are represented by the case statements in the
switch(logic_levels_in) construct. For those of you who
think in BASIC, the C switch statement works just like the
Select Case statement in BASIC. The braces that
surround the C switch construct are replaced by a
Select Case/End Select statement pair in the BASIC
implementation. In either language, the logic is identical.
The output of our firmware AND gate only goes high
when both of the inputs are logically high. This code is so
simple that one would think that debugging would be
totally unnecessary. Well, this seemingly simple piece of
code did not run properly at all.
The physical circuit behind the code snippet in
Listing 2 contains no visual aids, such as LEDs. So,
instead of pulling out a scope or logic probe, I simply
added putc (put character) statements inside of each of
the case statements. The putc arguments added in
Listing 3 match the case they are contained within.
For instance, if both inputs are logically low, the code
in the case 0x00: construct would be executed, which
would take the output of our firmware AND gate to a
logical low state.
Notice that I’ve commented out each of the AND
gate logical output states in the case constructs and
replaced them with putc statements that tell me
which case construct I have entered. I grounded
both of the input pins and executed the program.
Nothing was sent to the terminal emulator. Okay
... I then tied both of the inputs high. Still, nothing
showed up on the terminal emulator screen. I
decided to write a small serial routine to make
sure that data could indeed be sent by the PIC.
The code was very simple:
Listing 3. The As and the Zs were transmitted, but none of the putc
statements inside the case constructs fired.
//send A from the
//wait for half a
NUTS & VOLTS
#define gate_output_pin PIN_B2
logic_levels_in = input_b();
logic_levels_in &= 0x03;
putc(‘A’); //added later
putc(‘Z’); //added later
A string of As spurted across the terminal
emulator screen when I ran the little piece of
test code. That told me the hardware was
working as designed. I then put a putc(‘A’)
before the switch code and a putc(‘Z’) following
the switch code. The A and the Z both printed
in sequence, telling me that the code was
executing from top to bottom. However, I still
did not see any of the case numbers being
transmitted. I finally came to the conclusion
that the switch construct was not running and
turned to the assembler listing that the C
compiler generated for some clues.
Listing 4 is a part of the assembler code