Estoy tratando de implementar un programador de modo de bajo voltaje para el PIC18F2550 en un Arduino Uno de acuerdo con estas especificaciones de programación.
Las secuencias de bits se escriben en el PIC desde el bit menos significativo hasta el bit más significativo. También he tenido en cuenta los retrasos mínimos especificados en la hoja de datos, no parece haber retrasos máximos, excepto el tiempo de subida de MCLR/Vpp.
Para validar mi código, quiero leer el DeviceID en la dirección 0x3ffffe y 0x3fffff. Aquí está mi código:
/*
* Trying to build an arduino pic programmer for the PIC18F2550
* Programming specifications: http://ww1.microchip.com/downloads/en/DeviceDoc/39622L.pdf
* 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);
tableRead(0x3F, 0xFF, 0xFF);
// delay(500);
tableRead(0x3F, 0xFF, 0xFF);
exitingProgramming();
}
/*
* @param: three bytes which form the tablepointer address
*/
void setTablePTR(int addr_upper_byte,int addr_half_byte,int addr_lower_byte)
{
Serial.print("Set TablePTR to: 0x");
Serial.print(addr_upper_byte, HEX);
Serial.print(addr_half_byte, HEX);
Serial.println(addr_lower_byte, HEX);
writeBits(4, 0x0); // 4 bit command
writeBits(16, (0x0E << 8) + addr_upper_byte); // 16 bit data payload: load address
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
}
/*
* Read byte from the given address
*/
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;
//actual read
Serial.print("Read bits from LSB to MSB: ");
for (int i = 0; i < 8; i++)
{
digitalWrite(pgc, HIGH);
delayMicroseconds(3); //P14
if (digitalRead(pgd)==HIGH)
{
Serial.print("1");
data += (1 << i);
}
else
{
Serial.print("0");
}
digitalWrite(pgc, LOW);
delayMicroseconds(3);
}
delayMicroseconds(5); //P5A
pinMode(pgd, OUTPUT);
Serial.println();
Serial.print("Reading result: ");
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()
{
}
Este código ingresa al modo de programación, luego intenta leer desde 0x3fffff tres veces seguidas, finalmente sale del modo de programación. Lástima que estoy obteniendo tres resultados diferentes, aparentemente no estoy leyendo el DeviceID... El resultado impreso es:
Entered Low Voltage Programming
Set TablePTR to: 0x3FFFFE
Read bits from LSB to MSB: 00000111
Reading result: 224
Set TablePTR to: 0x3FFFFF
Read bits from LSB to MSB: 00011111
Reading result: 248
Set TablePTR to: 0x3FFFFF
Read bits from LSB to MSB: 00000000
Reading result: 0
Exiting Low Voltage Programming
Cuando conecto otro PIC18F2550, los resultados difieren. Ahora no sé cómo continuar para depurar este proyecto. ¿Alguien tiene experiencia con este asunto y / o algunas sugerencias?
p.d., sé que es más fácil usar un programador, pero esto es más divertido ;)
Lo primero que debe hacer para depurar algo como esto es verificar que realmente ingresó al modo de programación. La forma más confiable es usar la entrada del modo de programa de alto voltaje. Asegúrese de que el pin PGM se mantenga bajo durante este tiempo. También asegúrese de que todos los pines de alimentación y tierra estén conectados, ya sea que crea que los está usando o no, con una tapa de derivación en cada pin de alimentación.
Para verificar que ingresó al modo de programación, cambie algo que debería impulsar PGD, como la lectura de la instrucción TABLAT (0010). Siga esto con 8 bits cero, luego, en el siguiente flanco ascendente de PGC, el chip de destino debería cambiar a conducir PGD desde que anteriormente era de alta impedancia.
Una vez que esté funcionando, lo siguiente es leer el ID del dispositivo, ya que siempre es un valor fijo conocido. Esto es más complicado ya que debe ejecutar instrucciones básicas para cargar los tres bytes de TBLPTR y luego realizar una lectura.
Dado que todas estas interacciones son síncronas y el reloj es tuyo, puedes ir tan lento como quieras y observar todo en el osciloscopio pieza por pieza.
Sería útil si describiera exactamente cuál cree que es su proceso para intentar realizar estas operaciones. No, no voy a buscar código arduino. Hay demasiado entre eso y las líneas PGC y PGD.
EnojadoEE
Jager