23
DEBUGGING

General

It takes a long time to become a good debugger. It has taken me forever, and I am still learning and still not very good at it. The problem is that you must have a good understanding of the PIC you are using and come up with a solid design. Though this may seem pretty straightforward, it isn’t, especially if you are using a new PIC—and the PIC 16F877A we are discussing is new to most of us.

In plain English, this means that I really do not know how to tell you to become a good debugger. Even so, I need to give you some guidance to help you, so I have put down everything that came to mind as I was debugging the various projects in this book. In these paragraphs, I have allowed myself some repetition under the various headings so they can each stand alone.

At the end of the chapter, I have included some questions and answers that were the result of some discussions on the Web site for another project but that are also relevant to any discussion about the 16F877A PIC.

Debugging and Troubleshooting

Debugging is not a random process during which one might hope to get lucky. It is a very carefully thought out strategy to find out why a program is not behaving the way it was intended to and what needs to be done to correct the problem. You will have fixed the problem only if you can make the problem come back by undoing the fix. A vague suspicion that you might have fixed the problem by pressing on a warm component is not enough to conclude that the problem has actually been solved. You must be able to make the problem come back. This is exactly the reason why intermittent problems are so hard to fix. It’s hard to make them come and go on command. In other words, it is harder to clearly understand the problem because it is intermittent.

First Problem that Must Be Fixed: The Microcontroller Crystal Must Oscillate

If the PIC oscillator will not oscillate, nothing can be done to fix anything, so the first thing we must do is make sure the OSC lines are actually oscillating. The easiest way to check this is with an oscilloscope. If there are problems, the following points are relevant.

1. Remember that the LAB-X1 runs at 4 MHz out of the box. Your system should also be designed to run at 4 MHz so you can use the LAB-X1 as a test bed whenever you need to. This allows you to take the PIC back and forth between your project and the LAB-X1 to see where the problems are. This is not a trivial tool that we have at our casual disposal.

2. To start with, do all your projects with a 4 MHz crystal. Later, you can move to 20 MHz. It is easy enough to replace a crystal on a board.

3. If the crystal frequency does not match the DEFINE OSC statement in your program, there can/will be problems. If you are using a crystal or resonator, you must know what the frequency of the device is and your software must state this number in the OSC statement at the top of the program accurately. They must match.

4. The Configuration and Option pulldown menus in the programmer must match the actual conditions in the hardware and they must match each other.

START WITH THE FOLLOWING CHECKS ON THE HARDWARE SIDE

1. Make sure the microcontroller has power.

Make sure it is 5 volts on the money.

Make sure there is power to both sides of the microcontroller, as is required on a large number of them.

Make sure ground is a solid ground at all points in the circuitry. If the ground is squirrelly, this is not good. Fix it.

2. Make sure the MCLR pin has been pulled up to 5 volts with a 1K to 10K resistor. This value depends on the design you are using. Make sure the MCLR pin is actually high. Put a meter on it. Use an oscilloscope if you suspect transient operation.

3. Make sure the oscillator is running. Use an oscilloscope. Make sure the operation is consistent.

4. Use your eyes to check the PC board for shorts and dry solder joints. Use a magnifying glass in difficult areas. Go over questionable areas with a soldering iron again and recheck your work.

5. Make sure the wiring is what you think it is. Check the route of every wire. Mark it off on the schematic as you check it. Check the PC board trace routings where necessary.

6. Check and confirm the values of each of the components on the board.

7. Make sure each IC is oriented with pin 1 in the proper location in its socket.

8. Make sure power and ground to each IC are properly routed and are actually at the values they are supposed to be with appropriate instruments.

9. Measure voltages throughout the layout and confirm they are what they are supposed to be.

10. Make sure all capacitors are installed correctly. Check polarity where necessary.

11. Make sure all diodes are installed correctly. All of them don’t always need to be installed so the cathode is connected to ground. Confirm connections on all inductive loads.

12. Make sure all inductive (back electro motive force [EMF]) loads are properly protected against with diodes. Make sure these diodes are properly rated for amperage, voltage, and switching speed.

13. Use the oscilloscope to check for noise in the circuitry. Eliminate it by adding small capacitors to ground at the noisy areas.

14. Read the relevant chapter of the datasheet (on startup) again. Make sure you understand what the datasheet is saying.

15. Make sure the processor has not been destroyed. Sometimes one or more lines on various ports can be destroyed. Try a replacement unit.

MAKE THE FOLLOWING CHECKS ON THE SOFTWARE SIDE

1. Go over the software line by line and make sure there are no typos. Not all typing mistakes are identified by the compiler software.

2. Write a short LED blink routine and run that on the board to make sure the system is actually alive and working. If the program loops as part of its design, add a blinking instruction for one of the LEDs to tell you that the loop is actually executing as designed and not hanging up on some other segment of code.

3. Use MicroCode Studio to see what is going on in the system as it is run. The software is free to download off the Internet for individual users and will run the 16F877A. Details on using this software are beyond the scope of this book and are not covered here, but it’s worth the effort to learn this software.

4. For the preceding step, you can set up your PC as a dumb terminal and connect it to the board so the entire system can be viewed on the screen with the appropriate software.

5. Go over the software to make sure there are no logical errors.

6. Follow the use of each variable throughout the program to make sure it does not get modified where it should not.

7. The software we are using employs integer math and 8- and 16-bit variables. Make sure that none of the variables exceed the bounds that have been designated by the variable sizes. Be sure you understand what happens when registers overflow or underflow in integer math. You cannot use decimal points at most locations in integer math unless you take special precautions.

8. Read the “microprocessor start-up” chapter (Chapter 14) of the datasheet again. Make sure you understand what the datasheet is saying.

There are a number of ways to get input into and feedback out from a malfunctioning program. Using as many as possible will reduce the number of times you have to reload the program. You have the following feedback devices available to you. Incorporate what you need into critical areas of the program.

1. The LCD—use both line 1 and line 2, and use each character on each line.

2. The speaker—it’s simple to set up two tones that are easy to differentiate.

3. The dumb terminal program for a PC can display a large amount of information.

4. Use the various buttons to modify what is happening in the program in real time.

5. Use the three onboard potentiometers to input various values into the program and see how they modify its operation.

6. If more is needed, add LEDs to the hardware so you can turn them on and off at critical junctures.

7. Use the DEBUG command in PBP to send information to a dumb terminal. The use of this command is explained in detail in the PBP manual. See the following also.

You can insert a short loop that displays the registers you are interested in at a critical location in the program. When the program enters this loop, it indicates that the program actually got this far and then it displays the registers of interest again and again without going any further. This loop can be moved up and down through the program to see what is going on where.

8. Determine if the program is actually getting to a certain critical line of code.

9. Determine what the contents of various registers are at critical times in the code.

10. Look at how counters are behaving to confirm that this is exactly what is supposed to be happening.

11. Display data based on interrupts programmed and/or entered by you from the keys.

12. Look for areas where the program might be getting stuck in a loop.

13. Pay special attention to the handling of interrupts.

14. Go over the circuit layout to make sure there are no mistakes in the design of the circuitry.

15. Go over the physical circuit to make sure it is actually wired the way it was designed to be.

16. Make sure all lines that are to be pulled up or down are actually being pulled up and down and that the resistors being used are of the right values.

If the Chip Refuses to Run

If the chip refuses to run at all, check the configuration settings in the programmer software. The oscillator configuration is the most critical, but other settings can also prevent the PICmicro from starting up. See the “Special Features of the CPU” chapter in the datasheet (Chapter 14) for correct configuration details. The default settings for configuring the various conditions are discussed later near the end of this chapter.

Using the PBP Compiler Commands to Help Debug a Program

The PICBASIC PRO Compiler provides a number of commands that can be a tremendous help in debugging programs that refuse to cooperate. These commands can be broken down into a number of categories to better understand how they can be used.

Commands that Can Provide Debug Output to a Serial Port

A number of commands provided by the compiler do not have a function other than to aid in the debugging of programs by outputting data to a designated pin on the microcontroller. This data can then also be displayed on a dumb terminal.

The following commands are useful in the context. See the PBP manual for details.

DEBUG is like a print command to the serial port (as well as to the dumb terminal)

DEBUGIN

ENABLE

ENABLE DEBUG

DISABLE

DISABLE DEBUG

PEEK

POKE

SOUND

Dumb Terminal Programs

A number of terminal programs are available at no charge on the Internet. I use the dumb terminal program provided by Microsoft as a part of their operating system utilities. It provides all the functionality you need to use it with the PICBASIC PRO Compiler and MicroCode development software.

The Bray terminal program is a more sophisticated dumb terminal program and is available for free on the Internet.

Solderless Breadboards

Using solderless boards for your prototyping activities is, in general, not recommended. They are fine for small experimental excursions when you first start out with the microcontrollers, but as your circuitry gets more and more complicated, there is too great chance for poor connections and wires to come loose to use these devices.

It is recommended that you use the perforated boards that have a separate solder pad for each hole and solder each component into the board. Then, wire each of the components with hookup or wire wrap wire with straightforward point-to-point wiring. The key is to be very careful and thorough so there are no mistakes. It takes patience and care. Take your time and check your work before and after each connection is made.

(I also use circuit boards with continuous bars of conductors on them.)

Debugging at the Practical Level

Help! What do I do now? The project is “deader than a door nail” and I don’t have a clue!

A fairly long program that you wrote will not work the way it is supposed to. You don’t know if it is the software or the hardware and you do not have a clue as to what you should do. Don’t throw it all in the garbage just yet. Chances are that with a little bit of work everything will be just as you intended. After all, you did create all this code and the hardware.

The problem is that there is nothing to look at or see; the thing is dead, and you don’t know where to start. The solution is to make things visible and to start the process in a step-by-step manner so you can make sure each step in the program you have created is doing what it is supposed to do. The good news is that you do not have to spend a fortune on new software and hardware and you don’t have to spend a year of your life learning a new discipline. You already know and have everything you need to debug the program in your LAB-X1 board. Even if the circuitry you are using is divorced from what is on the LAB-X1, the software can still be tested and we can still make sure the PIC is not dead.

Three output devices on the LAB-X1 board can be used as aids in the debugging process. They are

sqr The LCD

sqr The eight LEDs in the LED bar

sqr The piezoelectric speaker device

A number of input devices can also aid in the debugging process by making the debugging more interactive. These devices are

sqr The keypad

sqr The three potentiometers

sqr The reset button

Some standard software tools can also be used:

sqr The PAUSE command

sqr The STOP command

sqr The IF… THEN couplet

sqr The ability to COMMENT out sections of code

The PICBASIC PRO Compiler provides a number of statements that are designed specifically for the debugging process. These are mentioned earlier and should be studied in the PBP manual.

The personal computer you are using is also a powerful debugging tool in that it can both send and receive information and gives you a full screen and a keyboard to use as interactive elements. PICBASIC PRO provides a number of powerful tools to let you interact with your PC. However, the most powerful device at your command is the computer between your ears. By and large, the debugging process is an exercise in the use of your brain. Everything else necessary can be done with the LAB-X1 and your personal computer.

Following a few rules will make the debugging process both easier and more likely to succeed in a reasonable time.

Rule 1. Be thinking about the debugging process as you write the code. Design the code so it can be debugged, and put in the necessary hooks and connects as you go along.

Rule 2. Write the code as small subroutines that can be tested as stand-alone mini-programs. Once you have the software working, you can streamline the code. Test your program as you develop it to make sure each developmental level is operational.

Rule 3. Do not wait till the last moment to start the debugging process. Debug as you go along, meaning that you should debug the code as it is developed rather than waiting till it is all done and ready to be delivered to the customer. Learn to write the code so you can debug it as sections of code or as stand-alone subroutines.

Rule 4. Write a set of routines that can be called from within the code that shows you the content of various memory locations on the LCD or bargraph as the program runs.

The first thing most programs must do is make the LCD come alive. Two things must be checked to confirm its proper operation. Is the software right? Have you somehow destroyed the electronics?

SOFTWARE

PBP (PICBASIC PRO) makes it completely painless to use the LCD. All you have to do is tell the software where the LCD is connected to the hardware and which pins are connected to what function on the LCD. In the case of the LAB-X1 board we are using, the LCD is connected as follows:

The LCD is connected to PORTD and PORTE

It can use the 4-bit or 8-bit mode to send data to the LCD (if all pins are connected).

The register select bit is at PORTE bit 0

The enable bit is at            PORTE bit 1

The read/write bit is          PORTE bit 2 and is made low for writing to the LCD

These variables are defined by the following code segment. This code should be placed at or near the beginning of your program.

  DEFINE LCD_DREG PORTD  ; LCD connected to PORTD
  DEFINE LCD_DBIT 4      ; uses 4 bit data path
  DEFINE LCD_RSREG PORTE ; RESET register is PORTE
  DEFINE LCD_RSBIT 0     ; uses bit 0
  DEFINE LCD_EREG PORTE  ; ENABLE register is PORTE
  DEFINE LCD_EBIT 1      ; uses bit 1
  PORTE.2 = LOW          ; we will be writing to only LCD

You must have a pause of about 0.5 seconds at the start of your program, before you first access the LCD, to allow the LCD to complete its setup routines. If this pause is omitted, the LCD can malfunction or may not start up at all. Just to make sure, start with a PAUSE of 0.5 seconds and then shorten it when you know that everything is working properly.

  PAUSE 500          ; and
  ADCON1 = %00000111 ; set the digital modes needed. This has to
                     ; do with
                     ; making PORTE digital for controlling the LCD.
                     ; PORTE is analog on startup and reset. PORTD
                     ; is digital only and cannot be made analog.
                     ; Set TRISD.

This is needed because the 16F877A starts up and resets to analog mode. In analog mode all of PORTE and PORTA are in analog mode. We need the three PORTE pins to be in digital mode so we can control the LCD. The preceding instruction does this. It also makes PORTA digital, but that is not always necessary.

Go over your code to make sure all the preceding conditions are met verbatim, and are case perfect.

Write a short program to check the operation of the LCD hardware as comprehensively as you think is necessary. Program 23.1 can be used as a quickie starter.

Program 23.1 A short rudimentary program for testing the LCD

  CLEAR                       ; clear variables
  DEFINE OSC 4                ; define osc
  DEFINE LCD_DREG PORTD       ; define LCD connections
  DEFINE LCD_DBIT 4           ;
  DEFINE LCD_RSREG PORTE      ;
  DEFINE LCD_RSBIT 0          ;
  DEFINE LCD_EREG PORTE       ;
  DEFINE LCD_EBIT 1           ;
  LOW PORTE.2                 ; pull write bit low
                              ;
  TRISD = %00000000           ; set all PORTD lines to outputs
  TRISE = %00000000           ;
  ADCON1 = %00000111          ; don’t forget to set ADCON
                              ;
  PAUSE 500                   ; pause .500 seconds for LCD startup
                              ;
  LCDOUT $FE, 1               ; clear LCD, go to first line, first
                              ; position
  LCDOUT “Now is the time for”   ; print
  LCDOUT $FE, $C0             ; go to second line
  LCDOUT “a cup of pea soup!” ; print
  END                         ; end program properly

A similar but more comprehensive program that you wrote and that you are completely comfortable with should be in your utility files to let you check the proper hardware and software operation of your LCD whenever you think it is necessary. Your program should check every character and every command in the LCD’s vocabulary if you want to perform a really comprehensive check.

Integer math is the source of a lot of problems for those who are unaware of the havoc that integer math calculations can visit on the software you are trying to debug. A certain amount of expertise with integer math is a must if you want to create mathematical routines within your software. If the routines are amenable to it, you should write a program around the routine to test every possibility that the routine might encounter and thus debug it the hard way even if it means your computer has to run the routine all night to get through all the commutations. Oftentimes, all that is necessary is to run the routines that would be called at the boundary conditions, or under the critical conditions, to make sure the routine is robust.

The following routine has a bug in it. See if you can find it. The routine is designed to make you aware of an 8-bit math problem.

We are trying to maintain a value of X = 127, but we need to do it in small steps. An external condition is changing X to anything from 1 to 255, and we cannot exceed these parameters because of the fact that X is a variable that has been defined as a byte.

  MODIFYX:            ;
  READ X              ;
  IF X<127 THEN X=X+5 ;

  IF X>127 THEN X=X-4 ;
  IF X<1 THEN X=1     ;
  IF X>255 THEN X=255 ;
  RETURN              ;

Twos compliment convention is not supported in the integer math used by the PIC compiler, nor is implementation of the minus (–) sign. If you are having problems rewriting the math formulas with brackets, changing the order in which things are done might help.

Configuring the 16F877A and Related Notes

The LAB-X1 is set to 4 MHz by default. This is set by the ABC jumpers on the board. If A is set at 2–3, then it is 4 MHz. Since the compiler writes the default oscillator configuration to XT every time, 4 MHz causes the fewest problems for new users. This means the compiler always uses XT unless you inhibit it. You should inhibit this only if you are not running at 4 MHz. If you are running your own circuit, you will, in all probability, not be using a frequency dividing network (like the one the LAB-X1 uses), so your frequency will be the frequency of the crystal you use. The PIC adjusts the power used by the oscillator to minimize power use (critical for battery-powered devices). At the XT setting, the PIC puts out less power because at 4 MHz less power is needed. If you are using a 20-MHz crystal, you should use the HS setting for the oscillator. At the HS setting, the PIC provides more power for the oscillator. Some times the system will run a 20-MHz crystal at the XT setting, but the operation can be marginal.

When working on projects faster then 4 MHz, and where power consumption isn’t critical, use a 20-MHz crystal. Uncheck the Update Configuration From File option in the programmer after changing to HS. This prevents the setting from reverting to XT every time a new hex file loads (as mentioned earlier).

The compiler always disables low-voltage programming by default. If you check the option Update Configuration From File in the programming software, this will make it to the chip. If you are setting configuration manually in the programmer software, simply select Disable for Low-Voltage Programming.

The configuration setting controls how the oscillator driver works on the PIC. It’s mainly a question of power consumption, but there also seems to be some filtering involved. If you’re using a 4-MHz crystal/resonator, the HS setting will work, but it will consume a bit more power than the XT setting. The XT setting won’t drive the faster crystals reliably, presumably because it doesn’t have the power.

The following is a situation for which there is currently no explanation. The LABX1 uses an external clock chip, which is essentially the same as a TTL oscillator source. When you use a 16F877 (not 16F877A) set to XT, it will work fine at 20 MHz. If you replace the PIC with a 16F877A, however, it won’t run at all. It requires the HS setting for 20 MHz, even though the oscillator source is external and the chip doesn’t have to drive a crystal.

If pin B.3 is acting weird and the program randomly stops/starts/resets, it suggests that you have enabled Low-Voltage Programming in the configuration screen of the programmer. You have to check this whenever you change the PIC you are using because it can change unexpectedly. (Meaning that I cannot predict when it will happen.)

QUESTION

If ADCON1 = 7, then does that mean that the TRIS registers have to be set for ports A and E to make them outputs. What is the effect of following ADCON1 = 7 with TRISA = 0 and PORTA = 0 on the PORTA A-to-D designations? This is important because the compiler does not clear the LCD on startup and can make it hard to see the effect of these commands in complicated circumstances.

ANSWER

The answer depends on what you are trying to accomplish. The TRIS registers are set to $FF on a reset, making all the pins inputs. If you need a pin on PORTA to be an output, you must clear the corresponding TRIS bit. Commands like LCDOUT set the TRIS automatically:

  ADCON1 = 7 ; configures pins for digital operation
  TRISA = 0  ; configures pins as outputs (PORTA value placed on
             ; pins)
  PORTA = 0  ; changes PORTA value (drives all pins low)

If you want to insure that PORTA has a specific value when it becomes active as an output, set the TRISA value last:

  ADCON1 = 7 ; configures pins for digital operation
  PORTA = 0  ; changes PORTA value (pins still inputs - floating)
  TRISA = 0  ; configures pins as outputs (PORTA value placed on pins)

The reset values of the registers are listed in the datasheets. They differ based on the type of reset, the PORT, and the PIC you are using. Some bits are set to 1 or 0, while others are specified as being “unknown” or “unchanged.”

QUESTION

What if ADCON1 does not set all the A and E ports to digital? If a PORTA pin is still analog and we try to set it high with TRISA, what happens?

ANSWER

This also depends on the PIC and the pin in question. This answer will suffice in the majority of cases. The output circuitry is not affected by the pin being configured as analog mode. Therefore, you can write to the port as a whole and it will work as expected:

  PORTA = $03
  TRISA = $00  ; RA0 and RA1 go high, even if analog

The problems occur when reading the pins. A digital read of the port always returns zeros for pins configured as analog. Because of the read-modify-write phenomenon, successive writes to different pins on a single port can produce unexpected results:

  TRISA = $00 ; set pins as outputs
  PORTA.0 = 1 ; RA0 goes high
  PORTA.1 = 1 ; RA1 goes high, but RA0 returns low unexpectedly

The behavior depends on the method used to send output. Avoid making changes one right after another to the same port to fix this! Add a short pause between commands.

The following applies to the Configuration and Option menus in the programmer software

Settings

Oscillator

XT (for 4-MHz crystal)

Watchdog

Enabled

Power up

Enabled (not critical)

Brownout

Enabled (not critical)

Low-voltage programming

Must be disabled

Flash program write

Enabled (critical only if using boot-loader)

No code or data protection

(Disable)

Set the oscillator to HS for speeds faster than 4 MHz.

Using a 20-MHz crystal is fine for most PICs. Check the datasheet for each unit.

Be sure to select the correct device number in the device ID box.

Configuration

Oscillator

4 MHz use XT

20 MHz use HS

Code protection

Disable

Watch dog timer postscalar

Disabled

Brownout reset

Disabled

 

Enable

Watch dog timer enable

Power up timer enable

Disabled

Enable

Brownout reset enable

Low voltage programmer enable

Disabled

Enable

Flash program write enable

External data bus width

Mode

Memory size

Ignore

Ignore

Ignore

Options

Enable

Program/verify code

Enable

Program/verify configuration

 

Enable

Program/verify data

Program/verify ID

Program/verify oscillator calibration

Program serial number

 

Ignore

Ignore

Ignore

DISABLE

Update configuration

Reread file before programming

if not then 4 MHz

Ignore

Enable

Erase before programming

 

Enable

Verify after programming

18Fxxx file data address x2

Ignore

Enable

Disable completion messages

Skip blank check

Ignore

Simple Checks

The following are some simple checks you should apply if the PIC still does not oscillate.

Check that the power is on to the project.

Check that the power is on to the programmer.

Check that the programmer is plugged into your board.

Check that there is a device in the main PIC socket.

Check that the device in there is orientated for pin 1.

Check that the ZIP socket is locked in position.

Check that the correct device has been selected.

Check that the program has an END statement.

Check that the addresses for all the DEFINEs for the project are correct.

Check the spellings. (The compiler does not catch everything!)

Check that everything is in capital letters where required (see PBP manual).

Check that all sockets that should be empty are actually empty.

Run a test program “suited to and designed for” your specific project.

Use an oscilloscope to check that the system is actually oscillating at the OSC pins.

In most programs, some other pins should also be going high and low regularly.

Recheck the wiring.

Check for open wires and cold solder joints.

Check for short circuits.

Recheck the program.

Run a program that you know works on your PIC.

Some Programmer-Related Error Messages

If the programming connector is not connected, you will get a code check error.

If the programmer has no power, you will get a communication error.

If the wrong device is selected, you will get a blanking error.

Occasionally, if everything is okay, you will get a code check error. Just reprogram the chip.

Things I Have Noticed but Have Not Figured Out (and Other Mysteries)

If you know the answer, send me an e-mail so we can all share the information.

Sometimes, for some reason INTCON.0 will be set at 1 on startup. If you clear it, it does not reset itself.

On startup, OPTION_REG is %11111111, but if you set it to %01111111, the system hangs up if PORTB is not set appropriately to reflect the need for the Option Register setting. Meaning that if the PORTB pins are to be pulled up, some of them have to be programmed as inputs or the thing can hang up!

Assign the prescalar to the watchdog timer to get 1:1 pre-scaling on Timer2. See page 21 of the datasheet.

B7 and B6 (and sometimes B7 alone) are pulled low by the programming cable of the parallel programmer under certain conditions. This can inhibit the use of these two pins by the software while the programmer is connected to the board.

The global interrupt enable bit is cleared whenever an interrupt is set and reset automatically when the interrupt bit is cleared by the program. This means no new interrupt can be set till you clear the last interrupt.

Set only one interrupt at a time and follow through till it is cleared.

There can be more than one “ON INTERRUPT GOTO” call within a program, so each interrupt can be handled individually. It is best to stick with one interrupt till you become proficient at working with the PICs.

When using the LCD, the clearing routine at the beginning of the program must be something like:

  PAUSE 500  ; pause for LCD start up
  LCDOUT $FE, 1, “Clearing the LCD” ; clear the display and
                                    ; show message.
  PAUSE 250     ; This is useful for seeing a reset
                ; button response
  LCDOUT $FE, 1 ; clear again to make sure you are starting
                ; with nothing in the LCD screen.

. . . because neither the compiler nor the CLEAR command clear the display on reset, and whatever happens to be in the display from the last program will stay in the display and mislead you. Since this can be confusing at the beginning of a program, it is your responsibility to clean this up.

Setting the Ports

All ports that will be used should be set for port configuration, and all pins that will not be used should be set as inputs. Setting them as inputs minimizes the possibility that an improperly set port pin will turn something on or off by mistake. It would not be out of line to actually set all other unused ports to inputs, though all ports are set to be inputs on startup. To know the exact official status of each port and register on startup and reset, see the datasheet. Some pins/bits may come up as undefined.

A cold start is not the same as a reset. If you are using the EEPROM in the chip, there can be added complications.