PIC/C18 Compiler Tips and Troubleshooting

From Mech
Revision as of 14:24, 11 October 2007 by Hwang (talk | contribs) (→‎Erratic Behavior at End of Program)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Troubleshooting

MPLAB Has Trouble Connecting to the ICD2

If you see the following errors while trying to connect to the ICD2:

ICD0192: Failed to clear COM error.  (RetVal = 0xFFFFFFF0, ErrRet = 0x0)
ICD0021: Unable to connect with MPLAB ICD 2

ICD0019: Communications:  Failed to open port: (Windows::GetLastError() = 0x2, 'The system cannot find the file specified.
')
ICD0021: Unable to connect with MPLAB ICD 2

Disconnect the reconnect the ICD2 from the USB port, then open the Device Manager (Control panel>System>Hardware>Device Manager) and disable then re-enable the ICD2. Also, be sure that you followed in installation instructions in the manual when you installed the ICD2.

printf

Note that printing floating point types with printf is not supported.

Data Corruption/Erratic Behavior

Beware if you have large arrays as local variables; you run the risk of a stack overflow. Try making large arrays global variables or static variables.

Serial Communications Data Corruption

If you are having trouble with RS-232 communications with other devices, remember that the RS-232 standard uses -8V to -15V for a low signal and 8V to 15V for a high signal, whereas the PIC uses 0V and 5V, respectively. If you are interfacing the PIC with a standard RS-232 device, such as the serial port on a PC, you will need a voltage shifting chip such as the ST232 RS-232 Voltage Shifter.

You should also beware that baud rates are usually not exact. The system's clock generally has to be an integer multiple of the baud rate, so if a device has a 1 MHz clock, it is likely to use a baud rate of 111,111.111 bps (1,000,000/9) instead of the standard 115,200 bps. Although these systems can generally tolerate small differences in the baud rate, the possibility of mismatched baud rates contributing to errors should be kept in mind.

Erratic Behavior at End of Program

If you have a program where the PIC runs through the program once and stops and does nothing until it is reset, place a while(1){} loop at the end of the program to make the PIC enter a trap state.

Changes to EEPROM Have No Effect

Try powering down and re-starting the PIC.

Tips

Splitting Multi-Byte Data Types into Individual Bytes

There are some situations where you may need to split a multi-byte variable into its component bytes (for example, writing to 16-bit registers or sending data through the serial port).

Using Unions

One way to do this is to use the union data type. A union is like a struct, except all the members share the same location in memory. Therefore, if have a union with one int variable and an array of two char variables, writing to the int variable will automatically fill in the char fields as well, and vice versa.

Example:

union UINT_UCHAR{
		unsigned int intVal;
		unsigned char charVal[2];
};

char byte1;
char byte2;

union UINT_UCHAR splitter;
splitter.intVal=0xABCD;
byte2=splitter.charVal[1]; //byte2 will equal 0xAB
byte1=splitter.charVal[0]; //byte1 will equal 0xCD

In the memory, it looks like this:

PIC C18 union.gif

(MSB=Most Significant Byte, LSB=Least Significant Byte)

Using Arithmetic

Another way of doing this is to use arithmetic. For a 16-bit integer, the most significant byte can be obtained by dividing the value by 256. The least significant byte can be obtained by using the modulus function with 256. Example:

int someInteger;
char byte1;
char byte2;

someInteger = 0xABCD;
byte2 = someInteger/256;
byte1 = someInteger%256;

If you want to join two values:

int someInteger;
char byte1;
char byte2;

byte2 = 0xAB;
byte1 = 0xCD;
someInteger = (unsigned int)byte2*256 + (unsigned int)byte1;

Beware that this isn't going to give you the correct result if you leave byte1 and byte2 as signed chars, because signed chars could be negative. Therefore, we place the (unsigned int) keywords to cast them as unsigned integers before performing the operations.