Arduino as a Pic Programmer!

Hi everyone!

Here is my first version of my PIC programmer : program your PIC from USB! Cheap and easy! Feel free to do what you want with this project, modify it, upgrade it publish it,... but just tell me what you've done so that I can share it with everybody ;)

It works with PIC 16F628 but should work with most pic16F; if you can try at home leave a message so that I can list the working PICs here!

Here is the circuit you need to make : You can change the resistor value between 330 and more. Always RESET Arduino before putting 12V (I don't know if we need to, but that's just a safe practice)

And here is the code :

/*
PIC programmer using Arduino
This program is distibuted "AS IS", I offer no garantee.
By Ronan Gaillard
 */
#define  CLOCK  9
#define  DATA   8
#define  VPP1   6
#define  VPP2   5
#define  VPP3   4
#define  PGM    10 //HIGH/LOW voltage select mode
#define  MCLR   11 //LOW voltage only

void setup() {                
  
  pinMode(CLOCK, OUTPUT);    
  pinMode(VPP1, OUTPUT);
  pinMode(VPP2, OUTPUT); 
  pinMode(VPP3, OUTPUT); 
  pinMode(DATA, OUTPUT);   
  pinMode(PGM, OUTPUT);  

  Serial.begin(9600);
  Serial.println("Started"); 
 //Serial.println("Send s to start (please put Vpp first)");
 while(true)
 {
   if (Serial.available() > 0)
   {
    if(Serial.read()=='s')//HIGH VOLTAGE MODE
   {
    //VIN should be around 12V max. is 13.5V 
   
   
   digitalWrite(VPP1, HIGH);
   digitalWrite(VPP2, HIGH);
   digitalWrite(VPP3, HIGH);

     Serial.print("D");
    break;
   } 
   else//low voltage mode
   {
  digitalWrite(PGM, LOW);
  digitalWrite(VPP1, LOW);
   digitalWrite(VPP2, LOW);
    digitalWrite(MCLR, LOW);
   digitalWrite(VPP3, LOW);
   delayMicroseconds(20);
   digitalWrite(VPP1, HIGH);
   digitalWrite(VPP2, HIGH);
   digitalWrite(VPP3, HIGH);
   delayMicroseconds(3);
   digitalWrite(PGM, HIGH);
     delayMicroseconds(3);
     digitalWrite(MCLR, HIGH);
     Serial.print("D");
    break;
   } 
   }
   
 }
}

void loop() {
  
  char command = '\0';
  
   if (Serial.available() > 0) {
     
     command = Serial.read();
     
     switch(command)
     {
     case 'b' :
      BulkEraseProgramMemory();
       
       Serial.print('D');
     break;
     
     case 'E' :
       EndOfProgramming();
       Serial.print('D');
       break;
     
     case 'r' :     
       char valeur[16];
       ReadDataFromProgramMemory(valeur);
       for(int i=0; i<14;i++)
       {
        Serial.print(valeur[i]); 
       }
       //Serial.print("D");
     break;
     
     case 'l' :
       char WritingValue[14];
       for(int i=0;i<14;i++)
       {
        while(Serial.available() == 0)
        {
        }        
        WritingValue[i] = Serial.read(); 
       }
      
       
       LoadDataCommandForProgramMemory(WritingValue);
       
       
       Serial.print('D');
       break;
       
     case 'w' :
       BeginProgrammingOnlyCycle();
       Serial.print('D');
     break;  
     
     case 'W' :
       BeginEraseProgrammingCycle();
       Serial.print('D');
     break;  
     
     case 'i' :
       IncrementAddress();
       Serial.print('D');
       break;
       
     case 'c' :
       char ConfigValue[14];
       for(int i=0;i<14;i++)
       {
        while(Serial.available() == 0)
        {
        }        
        ConfigValue[i] = Serial.read(); 
       }
       LoadConfiguration(ConfigValue);
       BeginProgrammingOnlyCycle();
       
       Serial.print('D');
       break;
       
     case 'R' :
       
     
       digitalWrite(VPP1, LOW);
       digitalWrite(VPP2, LOW);
       digitalWrite(VPP3, LOW);
       
       delay(3);
       
       digitalWrite(VPP1, HIGH);
       digitalWrite(VPP2, HIGH);
       digitalWrite(VPP3, HIGH);
       
       Serial.print("D");
       
     break;
       
     
     }
   }
  

}
void WriteBit(char nb)
{
  digitalWrite(CLOCK, HIGH);
  if(nb!='0')
  {
    digitalWrite(DATA,HIGH);
  }
  delayMicroseconds(3);
  digitalWrite(CLOCK, LOW);
  delayMicroseconds(3);
  
    digitalWrite(DATA,LOW);
  
}

byte ReadBit()
{
  byte valeur = 0;
  
  digitalWrite(CLOCK, HIGH);
  delayMicroseconds(3);
  if(digitalRead(DATA)==HIGH)
  {
   valeur = '1'; 
  }
  else
  {
    valeur = '0';
  }
  digitalWrite(CLOCK, LOW);
  delayMicroseconds(3);
  
  return valeur;
}
void ReadDataFromProgramMemory(char valeur[])
{
  digitalWrite(DATA,LOW);
  
  //Command
  
  WriteBit('0');
  WriteBit('0');
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  
  pinMode(DATA, INPUT);
  delayMicroseconds(3);
  
  //DATA
  ReadBit();
  for(int i =13;i>=0;i--)
  {
    valeur[i] = ReadBit();
  }
  ReadBit();
  
  
  
  pinMode(DATA, OUTPUT);
  
   
}

void LoadDataCommandForProgramMemory(char valeur[])
{
  digitalWrite(DATA,LOW);
  
  //Command
  
  WriteBit('0');
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  
  
  delayMicroseconds(3);
  
  //DATA
  WriteBit('0');//always 0
  for(int i =13;i>=0;i--)
  {
    WriteBit(valeur[i]);
  }
  WriteBit('0');//always 0 (stop bit)
  
  delayMicroseconds(3);
  
  
  

  
   
}
void BeginProgrammingOnlyCycle()
{
  digitalWrite(DATA,LOW);
  
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('1');
  WriteBit('1');
  WriteBit('0');
  
  
  delayMicroseconds(3);
  

  

  
  delay(20);
}

void BeginEraseProgrammingCycle()
{
  digitalWrite(DATA,LOW);
  
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  
  
  delayMicroseconds(3);
  

  

  
  delay(20);
}

void BulkEraseProgramMemory()
{
  digitalWrite(DATA,LOW);
  
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  
  
  delayMicroseconds(3);
  
  
  
  delayMicroseconds(3);
  
  delay(20);
}

void FullEraseProgramMemory()
{
  char Erase [] = {'1','1','1','1','1','1','1','1','1','1','1','1','1','1'};
  LoadDataCommandForProgramMemory(Erase);
  BulkEraseProgramMemory();
  BeginProgrammingOnlyCycle();
}

void IncrementAddress()
{
  digitalWrite(DATA,LOW);
  
  WriteBit('0');
  WriteBit('1');
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  
  
  delayMicroseconds(3);
}

void LoadDataCommandForDataMemory(char valeur[])
{
  digitalWrite(DATA,LOW);
  
  //Command
  
  WriteBit('1');
  WriteBit('1');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  
  
  delayMicroseconds(3);
  
  //DATA
  WriteBit('0');//always 0
  for(int i =13;i>=0;i--)
  {
    WriteBit(valeur[i]);
  }
  WriteBit('0');//always 0 (stop bit)
  
  delayMicroseconds(3);
  
  
  

  
   
}
void LoadConfiguration(char valeur[])
{
  digitalWrite(DATA,LOW);
  
  //Command
  
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  WriteBit('0');
  
  
  delayMicroseconds(3);
  
  //DATA
  WriteBit('0');//always 0
  for(int i =13;i>=0;i--)
  {
    WriteBit(valeur[i]);
  }
  WriteBit('0');//always 0 (stop bit)
  
  delayMicroseconds(3);
  
  
  

  
   
}

void EndOfProgramming()
{
  digitalWrite(DATA,LOW);
  
  //Command
  
  WriteBit('1');
  WriteBit('1');
  WriteBit('1');
  WriteBit('0');
  WriteBit('1');
  WriteBit('0');
  
  delayMicroseconds(3);
}

To program use your COM port, here are the commands :

Just after RESET send s to start with HVP (High Voltage Programming) or S to start with Low Voltage Programming

wXXXXXXXXXXXXXX : writes word to location pointed by PC (program counter)
i : increases PC
r : read current location
e : erase full program memory
R : resets the PIC (PC to 0)
Every command returns character D if success

To Do : - This only reads and writes to program memory on PIC, improve it to access DATA memory(=EEPROM) - Support more PICs

Supported PICs : (Your PIC is not listed here? Don't hesitate to post a comment here so that I can add it!) Most 16F pics should be supported

Don't hesitate to tell me if it works with other PICs.


Latest updates : 03/03/2012 : updated C# prog + arduino code 24/02/2012 : uploaded new Software that writes to Prog memory and loads the Configuration Word, and uploaded the Arduino Firmware, which supports LVP (Low Voltage Programming) by sending 'S' just after RESET. 22/02/2012 : updated the C# code : you can now burn HEX file to PIC! (only program memory supported, not EEPROM and Config word) 21/02/2012 : added the reset command, and started to program a C# program to send HEX to PIC


Here is a 18f programmer : https://sites.google.com/site/thehighspark/arduino-pic18f Special thanks to kirill578!

Enjoy, Soranne

Here is the start of the C# prog used to control the Arduino PIC programmer, not finished at all, just a start :wink: (updated on 24/02/2012)


You need to :

  • reset Arduino before starting the prog/reading/writing
  • don’t forget the 12V
  • .NET Run Time 4.0 (should already be on your PC if you use Windows)

See end of post for download

As this is just a prototype I encourage you to check your PIC memory with your normal programmer.

ArduinoPic.zip (8.28 KB)

That is an interesting project. I will figured out this project, doing experiments amd try it.

Thank Soranne. Merci <-- In english in this section. :D

HI Sorraine such a nice project i have different types of pic's a few putting up with me lying around without a JDM programmer usage as my desktop us ruined it cant be used on laptop so i can check with those pic's.

i just wanted that can you provide intallable exe file of your c# programme which is used to programme pic's (i dnt have visual c# IDE installed and configured)

That is an interesting project. I will figured out this project, doing experiments amd try it.

Thank Soranne. Merci <-- In english in this section.

Thank you for your comment :) Merci!

HI Sorraine such a nice project i have different types of pic's a few putting up with me lying around without a JDM programmer usage as my desktop us ruined it cant be used on laptop so i can check with those pic's.

i just wanted that can you provide intallable exe file of your c# programme which is used to programme pic's (i dnt have visual c# IDE installed and configured)

Hi NI$HANT, Thank you for your comment too! For the moment I'm not providing the *.exe because the program doesn't burn the hex file yet :s . As soon as I have improve the program I will post the *.exe here ;) This afternoon (it's now 09:06 in France ;) ) I will certainly have a good c# program running so I will post the exe here !

Thanks a lot SOrraine, Im waiting for it impatiently.do not want to struggle for with parallel programmers and serial programmers any more.

Hi, I uploaded the C# prog to the second post. See indication on second post ;) Enjoy!

I'm the First to Download it, but im sure not the last! :D

Thanks! :) I just noticed there may be a problem : the software might writeMSB (Most Significant Byte) first whereas it should write LSB (Least Significant Byte) first. I'll check this afternoon! Have a nice day!

EDIT : i fixed everything, I also added configuration word support. But I have an internet problem so I can't upload my code and .exe yet :s

@ Soranne, Hi thanks for prompt update, I'm eagerly waiting for the latest .exe file and code, please prompt ASAP.

Working on LVP (Low Volatage Mode = no need for 12V) and release the code in less than one hour!

PS : just received my 16F876A, so I'm gonna try! ;)

EDIT : ARRRRRHHHHH having problemes with LVP :s Doesn't work, actually 16F876 don't work like 16F628, that's a bit more complicated than ithought. Anybody who want to help is welcome!

I think Sorrance giving external 12v to programme should not be that much of a headache for us Arduino Dude's :D for us the fact that arduino is being able to route the binary into the chip is enough and also these Stubborn PIC's would not that easily let one access them in low voltage mode ,However some would but not all.

Yeah that was just a test, too much trouble yet, I'll try it later. I just posted the software and new Arduino code up there :)

I just downloaded the latest code from the second post and want to know that whether you want to give me some instructions on using it.

Just follow what the program says and put your hex file in C:/mem.hex And before starting the prog reset the Arduino, it should work ;)

and.... if i want to extract out the program from PIC then i will find the HEX in C:\

??

No not implemented yet :s

But don't worry I'm working on that ;)

By the way, I'm working on the GUI, so that everything gets simpler, here is how it should look :

That is further very nice, but how long will it take?

I may finish it in less than one hour if everything goes well.

As I'm a student, and that the holidays fiinishe today I will only be able to post updates on week-end from now on.

That is fine Sorrane, i look forward to the finalization.