# Programming PIC18F2550 with an Arduino

I'm trying to implement a low voltage mode programmer for the PIC18F2550 in an Arduino Uno according to these programming specifications.

Bit-sequences are written to the PIC least significant bit to most significant bit. Also I've taken into account the minimum delays specified in the data sheet, there do not seem to be maximum delays, except for MCLR/Vpp rise time.

To validate my code, I want to read the DeviceID at address 0x3ffffe and 0x3fffff. Here is my code:

    /*
* Trying to build an arduino pic programmer for the PIC18F2550
* Author: Ingmar Jager
*/

//Arduino Pinout
int pgc = 9;  // program clock
int pgd = 8;  // program data
int pgm = 10;  // program mode
int MCLR = 11; //Master Clear Reset / Vpp

void setup()
{
Serial.begin(9600);

pinMode(pgc, OUTPUT);
pinMode(pgd, OUTPUT);
pinMode(pgm, OUTPUT);
pinMode(MCLR, OUTPUT);
digitalWrite(pgc, LOW);
digitalWrite(pgd, LOW);
digitalWrite(pgm, LOW);
digitalWrite(MCLR, LOW);
delay(500);

enterProgramming();
delay(500);
tableRead(0x3F, 0xFF, 0xFF); //read DeviceID2 at 0x3FFFFF. Should be 0x12 = 00010010

//delay(500);
// delay(500);
exitingProgramming();
}

/*
* @param: three bytes which form the tablepointer address
*/
{

Serial.print("Set TablePTR to: 0x");

writeBits(4, 0x0); // 4 bit command

writeBits(4, 0x0);
writeBits(16, 0x6EF8);  // set TBLPTR_U to addr_upper_byte

writeBits(4, 0x0);
writeBits(16, (0x0E << 8) + addr_half_byte);

writeBits(4, 0x0);
writeBits(16, 0x6EF7); //TBLPTR_H

writeBits(4, 0x0);
writeBits(16, (0x0E << 8) + addr_lower_byte);

writeBits(4, 0x0);
writeBits(16, 0x6EF6); //TBLPTR_L

}

/*
*/
void tableRead(int high_byte, int mid_byte, int low_byte)
{

setTablePTR(high_byte,mid_byte,low_byte);

writeBits(4, 0x9); //1000 = Read and no increment
writeBits(8, 0x00);
pinMode(pgd, INPUT);
delayMicroseconds(5); //P6

byte data = 0;
Serial.print("Read bits from LSB to MSB: ");
for (int i = 0; i < 8; i++)
{
digitalWrite(pgc, HIGH);
delayMicroseconds(3); //P14

{
Serial.print("1");
data += (1 << i);
}
else
{
Serial.print("0");
}

digitalWrite(pgc, LOW);
delayMicroseconds(3);
}

delayMicroseconds(5); //P5A
pinMode(pgd, OUTPUT);
Serial.println();
Serial.println(data);

}

/* Write LSB to MSB
* @param n = number of bits to write
* @param value = value to write in n bits
*/
void writeBits(int n, int value)
{

for (int i = 0; i < n; i++) {
if(boolean ((value >> i) & 1))
{
digitalWrite(pgd,HIGH);
//   Serial.println("Write High");
} // else Serial.println("Write Low");
}
digitalWrite(pgc, HIGH);
delayMicroseconds(3);
digitalWrite(pgc, LOW);
delayMicroseconds(3);
digitalWrite(pgd,LOW);
delayMicroseconds(5); //P5A
}

/*
* Entering low voltage programming signals
*/
void enterProgramming()
{
digitalWrite(pgc, LOW);
digitalWrite(pgd, LOW);
digitalWrite(pgm, LOW);
digitalWrite(MCLR, LOW);

delayMicroseconds(20);

digitalWrite(pgm, HIGH);
delayMicroseconds(3);//P15
digitalWrite(MCLR, HIGH);
delayMicroseconds(3);//P12
Serial.println("Entered Low Voltage Programming");
}

/*
* Exiting low voltage programming signals
*/
void exitingProgramming()
{
digitalWrite(pgc, LOW);
digitalWrite(pgd, LOW);
delayMicroseconds(1); //P16
digitalWrite(MCLR, LOW);
delayMicroseconds(1); //P18
digitalWrite(pgm, LOW);
Serial.println("Exiting Low Voltage Programming");
}

void loop()
{

}


This code enters programming mode, then tries to read from 0x3fffff three times in a row, finally exits programming mode. Too bad I'm getting three different results, apparently I'm not reading the DeviceID... The printed result is:

Entered Low Voltage Programming
Set TablePTR to: 0x3FFFFE
Read bits from LSB to MSB: 00000111
Set TablePTR to: 0x3FFFFF
Read bits from LSB to MSB: 00011111
Set TablePTR to: 0x3FFFFF
Read bits from LSB to MSB: 00000000
Exiting Low Voltage Programming


When I connect an other PIC18F2550 the results differ. Now I don't know how to continue to debug this project. Does anyone has experience with this matter and/or some suggestions?

p.s. I know it is easier to just use a programmer, but this is more fun ;)

• Have you looked at any of the lines with an oscilloscope to verify your timing? I wouldn't trust the delay functions to be very accurate for low values. Apr 30 '12 at 13:11
• @AngryEE, You're right in not trusting the delay functions, however no maxima are specified for the delays. So I think that shouldn't be a problem. If I can get my hands on a scope I will be checking it though. Apr 30 '12 at 17:35