PIC/C18 Compiler Tips and Troubleshooting

From Mech
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.

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.

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 = (int)byte2*256 + byte1;