|
|
View previous topic :: View next topic |
Author |
Message |
Stephanfo
Joined: 28 Nov 2004 Posts: 5
|
Library to program/verify a microchip PIC12F629/675 |
Posted: Tue Apr 25, 2006 2:41 am |
|
|
Hi all,
I wrote this library to allow you to program PIC12F629/675 from another microcontroller.
This library will allow you to make a PIC duplicator or a standalone programmer. I make this library for my company, to include the programing step with the product tester.
This library also calculate the 16bits checksum like MPLAB.
The two microcontrollers are directly connected, only an external circuit is needed to change the voltage from 5V to 12V (with a NPN and PNP for example).
Code: | ////////////////////////////////////////////////////////////////////////////
//// ISPROG.c ////
//// Library to program/verify a microchip PIC12F629/675 ////
//// ////
////////////////////////////////////////////////////////////////////////////
/********************************************************
* Start of the config *
********************************************************/
// Assign connection between programer and microcontroleur
// It's possible to reverse the signal by set TRUE the reverse mode
#define ISPROG_MCLR_PIN PIN_C5
#define ISPROG_MCLR_REV FALSE
#define ISPROG_VCC_PIN PIN_E0
#define ISPROG_VCC_REV FALSE
#define ISPROG_DATA_PIN PIN_E1
#define ISPROG_DATA_REV FALSE
#define ISPROG_CLOCK_PIN PIN_E2
#define ISPROG_CLOCK_REV FALSE
// Slower coef in case CLOCK > 40MHz, set 2 or more
#define ISPROG_SLOWER 1
/********************************************************
* End of the config *
********************************************************/
#define ISPROG_MCLR_HIGH output_bit(ISPROG_MCLR_PIN, !ISPROG_MCLR_REV)
#define ISPROG_MCLR_LOW output_bit(ISPROG_MCLR_PIN, ISPROG_MCLR_REV)
#define ISPROG_VCC_HIGH output_bit(ISPROG_VCC_PIN, !ISPROG_VCC_REV)
#define ISPROG_VCC_LOW output_bit(ISPROG_VCC_PIN, ISPROG_VCC_REV)
#define ISPROG_DATA_HIGH output_bit(ISPROG_DATA_PIN, !ISPROG_DATA_REV)
#define ISPROG_DATA_LOW output_bit(ISPROG_DATA_PIN, ISPROG_DATA_REV)
#define ISPROG_CLOCK_HIGH output_bit(ISPROG_CLOCK_PIN, !ISPROG_CLOCK_REV)
#define ISPROG_CLOCK_LOW output_bit(ISPROG_CLOCK_PIN, ISPROG_CLOCK_REV)
#if ISPROG_DATA_REV == FALSE
#define ISPROG_DATA_READ input(ISPROG_DATA_PIN)
#else
#define ISPROG_DATA_READ !input(ISPROG_DATA_PIN)
#endif
// Command mapping
#define ISPROG_READ_PROG_COMMAND 0b00000100
#define ISPROG_READ_MEM_COMMAND 0b00000101
#define ISPROG_INCREMENT_COMMAND 0b00000110
#define ISPROG_LOADCONFIG_COMMAND 0b00000000
#define ISPROG_ERASEPROG_COMMAND 0b00001001
#define ISPROG_ERASEMEM_COMMAND 0b00001011
#define ISPROG_LOADPROG_COMMAND 0b00000010
#define ISPROG_LOADMEM_COMMAND 0b00000011
#define ISPROG_PROGINTERNAL_COMMAND 0b00001000
#define ISPROG_PROGEXTERNAL_COMMAND 0b00011000
#define ISPROG_ENDPROGEXT_COMMAND 0b00001010
// Constant to identify the device
#define ISPROG_UC_ID_ADDRESS 0x06
#define ISPROG_UC_629_ID 0x0F80
#define ISPROG_UC_675_ID 0x0FC0
#define ISPROG_UC_630_ID 0x10C0
#define ISPROG_UC_676_ID 0x10E0
// Constant to determine the revision
#define ISPROG_UC_REV_MASK 0x001F
// Memory size
#define ISPROG_PROG_SIZE 0x0400
#define ISPROG_EEPROM_SIZE 0x0080
// Calibration word address
#define ISPROG_OSCCAL_ADDRESS 0x03FF
// Configuration bit address
#define ISPROG_CONFIG_ADDRESS 0x07
#define ISPROG_CONFIG_UTIL_MASK 0x01FF
#define ISPROG_CONFIG_SAVE_MASK 0x3000
// Variable to save important register/config
int16 ISPROG_osccal_value = 0x3FFF;
int16 ISPROG_config_word = 0x3000;
// Variable to know the actual memory position and programming state
int16 ISPROG_Current_Address = 0;
int1 ISPROG_In_PV_Mode = FALSE;
/****************************************************************
********* 1st level sequences *********
********* call these sequences only if you *********
********* know what you're doing *********
****************************************************************/
// Exit from any state of the microncontroleur
void ISPROG_Standby(void)
{
ISPROG_MCLR_LOW;
ISPROG_VCC_LOW;
ISPROG_DATA_LOW;
ISPROG_CLOCK_LOW;
delay_us(10);
ISPROG_In_PV_Mode = FALSE;
}
// Enter into Program/Verify mode
void ISPROG_PVMode(void)
{
// Set each output low before entering into the sequence
ISPROG_Standby();
// Enter into Program/Verufy mode
ISPROG_MCLR_HIGH;
delay_us(10);
ISPROG_VCC_HIGH;
delay_us(10);
ISPROG_In_PV_Mode = TRUE;
ISPROG_Current_Address = 0;
}
// Read data from program memory command
int16 ISPROG_Read_Prog(void)
{
int8 i;
int16 data = 0;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_READ_PROG_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Config DATA as input
output_float(ISPROG_DATA_PIN);
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
// Start bit
// First cycle to set microcontroleur as output
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
// Read DATA
for(i=0;i<14;i++)
{
// Set clock high
ISPROG_CLOCK_LOW;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Test and store the bot of the data
data |= (int16)ISPROG_DATA_READ << i;
// Set clock high
ISPROG_CLOCK_HIGH;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Stop bit
// Last cycle to set microcontroleur as input
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Set DATA low
ISPROG_DATA_LOW;
// Needed delay between consecutive command
delay_us(1);
return data;
}
// Read data from EEPROM memory command
int16 ISPROG_Read_Mem(void)
{
int8 i;
int16 data = 0;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_READ_MEM_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Config DATA as input
output_float(ISPROG_DATA_PIN);
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
// Start bit
// First cycle to set microcontroleur as output
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
// Read DATA
for(i=0;i<14;i++)
{
// Set clock high
ISPROG_CLOCK_LOW;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Test and store the bot of the data
data |= (int16)ISPROG_DATA_READ << i;
// Set clock high
ISPROG_CLOCK_HIGH;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Stop bit
// Last cycle to set microcontroleur as input
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Set DATA low
ISPROG_DATA_LOW;
// Needed delay between consecutive command
delay_us(1);
return data;
}
// Increment address for program and memory
void ISPROG_Inc_Address(int16 increment)
{
int8 i;
ISPROG_Current_Address += increment;
for(;increment>0;increment--)
{
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_INCREMENT_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Set DATA low
ISPROG_DATA_LOW;
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
}
}
// Load Configuration (move to adress 0x2000)
void ISPROG_Load_Config(int16 config)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_LOADCONFIG_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
// Start bit
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Write DATA config
for(i=0;i<14;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set Data according to config
if(bit_test(config, i))
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// Set clock low
ISPROG_CLOCK_LOW;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Stop bit
// Last cycle to set microcontroleur as input
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Set DATA low
ISPROG_DATA_LOW;
// Needed delay between consecutive command
delay_us(1);
ISPROG_Current_Address = 0;
}
// Bulk Erase Program Memory
void ISPROG_Erase_Prog(void)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_ERASEPROG_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Set DATA low
ISPROG_DATA_LOW;
// Wait >1?s, TDLY1, TDLY2
delay_ms(8);
}
// Bulk Erase Data Memory
void ISPROG_Erase_Mem(void)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_ERASEMEM_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Set DATA low
ISPROG_DATA_LOW;
// Wait >1?s, TDLY1, TDLY2
delay_ms(8);
}
// Load data for program memory command
void ISPROG_Load_Prog(int16 data)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_LOADPROG_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
// Start bit
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Write DATA config
for(i=0;i<14;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set Data according to config
if(bit_test(data, i))
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// Set clock low
ISPROG_CLOCK_LOW;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Stop bit
// Last cycle to set microcontroleur as input
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Set DATA low
ISPROG_DATA_LOW;
// Needed delay between consecutive command
delay_us(1);
}
// Load data for eeprom memory command
void ISPROG_Load_Mem(int16 data)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_LOADMEM_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
// Start bit
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Write DATA config
for(i=0;i<14;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set Data according to config
if(bit_test(data, i))
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// Set clock low
ISPROG_CLOCK_LOW;
// delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Stop bit
// Last cycle to set microcontroleur as input
ISPROG_CLOCK_HIGH;
delay_cycles(ISPROG_SLOWER);
ISPROG_CLOCK_LOW;
delay_cycles(ISPROG_SLOWER);
// Set DATA low
ISPROG_DATA_LOW;
// Needed delay between consecutive command
delay_us(1);
}
// Programming (Internally Timed)
// Value are erased before been written
void ISPROG_Programming_Internal(void)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_PROGINTERNAL_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Set DATA low
ISPROG_DATA_LOW;
// Wait >1?s, TDLY1, TDLY2
delay_ms(6);
}
// Programming (Externally Timed)
// Value are not erased before been written, part must be erased
void ISPROG_Programming_External(void)
{
int8 i;
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_PROGEXTERNAL_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Set DATA low
ISPROG_DATA_LOW;
// Wait >1?s, TDLY1, TDLY2
delay_ms(2);
// Send the command
for(i=0;i<6;i++)
{
// Set clock high
ISPROG_CLOCK_HIGH;
// Set Data according to command
if((ISPROG_ENDPROGEXT_COMMAND & (1<<i)) != 0)
ISPROG_DATA_HIGH;
else
ISPROG_DATA_LOW;
// TSET1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
// Set clock low
ISPROG_CLOCK_LOW;
// THLD1 delay (>100ns)
delay_cycles(ISPROG_SLOWER);
}
// Set DATA low
ISPROG_DATA_LOW;
// Wait >1?s, TDLY1, TDLY2
delay_us(1);
}
/****************************************************************
********* 2nd level sequences *********
****************************************************************/
/****************************************************************
********* Single shot actions *********
****************************************************************/
// Erase all the part (EEPROM, Config, Program)
// and exist from P/V mode (needed to return to address 0x0000)
int1 ISPROG_Erase_All(void)
{
// Enter into Program/Verify mode
ISPROG_PVMode();
// Move to calibration oscillator word
ISPROG_Inc_Address(ISPROG_OSCCAL_ADDRESS);
// Save OSCCAL value to be able to restore it during programming sequence
ISPROG_osccal_value = ISPROG_Read_Prog();
// Control if OSCCAL is correct
if((ISPROG_osccal_value & 0x3C00) != 0x3400)
{
// Exit from Program/Verify mode
ISPROG_Standby();
// Return the failure of the erasing sequence
return FALSE;
}
// Jump to Config word and save it
ISPROG_Load_Config(0xFFFF);
ISPROG_Inc_Address(ISPROG_CONFIG_ADDRESS);
ISPROG_config_word = ISPROG_Read_Prog() & ISPROG_CONFIG_SAVE_MASK;
// Bulk Erase Program Memory and config if address is 0x2000-7
ISPROG_Erase_Prog();
// Bulk Erase Data Memory
ISPROG_Erase_Mem();
// Exit from Program/Verify mode
ISPROG_Standby();
// Return that the erase sequence iwas fine
return TRUE;
}
// Write one word into the program memory
int1 ISPROG_Write_One_Program(int16 IDWord, int16 Location)
{
// Enter into Program/Verify mode
ISPROG_PVMode();
// Increment address
ISPROG_Inc_Address(Location);
// Load Opcode before program it
ISPROG_Load_Prog(IDWord);
// Program it
ISPROG_Programming_External();
// Verify the data
if(ISPROG_Read_Prog() == IDWord)
{
// Exit from Program/Verify mode
ISPROG_Standby();
return TRUE;
}
else
{
// Exit from Program/Verify mode
ISPROG_Standby();
return FALSE;
}
}
// Change a value at the sp飩fic address
// The sequence will erase the value before write
// So, it's not necessary to erase all part before
void ISPROG_Change_EEPROM(int16 address, int8 data)
{
// Enter into Program/Verify mode
ISPROG_PVMode();
// Move to calibration oscillator word
ISPROG_Inc_Address(address);
ISPROG_Load_Mem((int16)data);
ISPROG_Programming_Internal();
// Exit from Program/Verify mode
ISPROG_Standby();
}
// Allow a easy read of a EEPROM BYTE
int8 ISPROG_Read_EEPROM(int16 address)
{
int16 data;
// Enter into Program/Verify mode
ISPROG_PVMode();
// Move to calibration oscillator word
ISPROG_Inc_Address(address);
data = ISPROG_Read_Mem();
// Exit from Program/Verify mode
ISPROG_Standby();
return data;
}
int16 ISPROG_Read_IDLocation(int8 IDAddress)
{
int16 data;
// Enter into Program/Verify mode
ISPROG_PVMode();
// Jump to Config address
ISPROG_Load_Config(0xFFFF);
// Increment address
ISPROG_Inc_Address(IDAddress);
data = ISPROG_Read_Prog();
// Exit from Program/Verify mode
ISPROG_Standby();
return data;
}
// Allow a easy read of a Config
int16 ISPROG_Read_ConfigWord(void)
{
return ISPROG_Read_IDLocation((int8)ISPROG_CONFIG_ADDRESS);
}
// Allow a easy read of the type of microcontroler
int16 ISPROG_Read_Device_ID(void)
{
return ISPROG_Read_IDLocation((int8)ISPROG_UC_ID_ADDRESS) & ~(int16)ISPROG_UC_REV_MASK;
}
// Allow a easy read of the microcontroler revision
int16 ISPROG_Read_Device_Rev(void)
{
return ISPROG_Read_IDLocation((int8)ISPROG_UC_ID_ADDRESS) & ISPROG_UC_REV_MASK;
}
// Write the 4 ID Location
int1 ISPROG_Write_All_IDLocation(int16 IDLocation[4])
{
int8 i;
int1 Verif_OK = TRUE;
// Enter into Program/Verify mode
ISPROG_PVMode();
// Jump to Config address
ISPROG_Load_Config(0xFFFF);
for(i=0;i<4;i++)
{
// Load Opcode before program it
ISPROG_Load_Prog(IDLocation[i]);
// Program it
ISPROG_Programming_External();
// Verify the data
if(ISPROG_Read_Prog() != IDLocation[i])
Verif_OK = FALSE;
// Increment address
ISPROG_Inc_Address(1);
}
// Exit from Program/Verify mode
ISPROG_Standby();
return Verif_OK;
}
// Write one word into an IDLocation
int1 ISPROG_Write_One_IDLocation(int16 IDWord, int16 Location)
{
// Enter into Program/Verify mode
ISPROG_PVMode();
// Jump to Config address
ISPROG_Load_Config(0xFFFF);
// Increment address
ISPROG_Inc_Address(Location);
// Load Opcode before program it
ISPROG_Load_Prog(IDWord);
// Program it
ISPROG_Programming_External();
// Verify the data
if(ISPROG_Read_Prog() == IDWord)
{
// Exit from Program/Verify mode
ISPROG_Standby();
return TRUE;
}
else
{
// Exit from Program/Verify mode
ISPROG_Standby();
return FALSE;
}
}
// Write the Config Word
int1 ISPROG_Write_ConfigWord(int16 ConfigWord)
{
// Write Word to Config location
return ISPROG_Write_One_IDLocation((ConfigWord & ISPROG_CONFIG_UTIL_MASK) | (ISPROG_config_word & ISPROG_CONFIG_SAVE_MASK), ISPROG_CONFIG_ADDRESS);
}
// Calculate the checksum of the programe memory and config word
int16 ISPROG_Checksum(void)
{
int16 Checksum = 0;
int16 Address;
// Enter into Program/Verify mode
ISPROG_PVMode();
for(Address=0;Address<ISPROG_PROG_SIZE;Address++)
{
if(Address != ISPROG_OSCCAL_ADDRESS)
Checksum += ISPROG_Read_Prog();
// Increment address
ISPROG_Inc_Address(1);
}
// Exit from Program/Verify mode
ISPROG_Standby();
// Add Config word to Checksum
Checksum += ISPROG_Read_ConfigWord() & ISPROG_CONFIG_UTIL_MASK;
// Return the value of the checksum
return Checksum;
}
/****************************************************************
********* multiple and sequential actions *********
****************************************************************/
// Prepare the microcontroleur for a complete writing
// of is program memory or EEPROM memory
void ISPROG_Init_Writing(void)
{
// Enter into Program/Verify mode
ISPROG_PVMode();
}
// Write a opcode into the program memory and control it
// After, increment the counter
int1 ISPROG_Prog_Writing(int16 data)
{
// Test if the microcontroleur has been set up in PVmode
if(ISPROG_In_PV_Mode == FALSE)
return FALSE;
if(ISPROG_Current_Address == ISPROG_OSCCAL_ADDRESS)
data = ISPROG_osccal_value;
// Load Opcode before program it
ISPROG_Load_Prog(data);
// Program it
ISPROG_Programming_External();
// Verify the data
if(ISPROG_Read_Prog() == data)
{
ISPROG_Inc_Address(1);
return TRUE;
}
else
{
ISPROG_Inc_Address(1);
return FALSE;
}
}
// Write a Byte into the EEPROM memory and control it
// After, increment the counter
int1 ISPROG_EEPROM_Writing(int8 data)
{
// Test if the microcontroleur has been set up in PVmode
if(ISPROG_In_PV_Mode == FALSE)
return FALSE;
// Load Opcode before program it
ISPROG_Load_Mem((int16)data);
// Program it
ISPROG_Programming_External();
// Verify the data
if(ISPROG_Read_Mem() == data)
{
ISPROG_Inc_Address(1);
return TRUE;
}
else
{
ISPROG_Inc_Address(1);
return FALSE;
}
}
// Once programming is finished, switchoff ?c
void ISPROG_Stop_Writing(void)
{
// Exit from Program/Verify mode
ISPROG_Standby();
} |
I wrote a small example which program incremental value into Program and EEPROM memories. The config word is 0x3199 and the IDLocation are filled with incremental value too.
Code: | int16 IDWORD[] = {0x0000, 0x0001, 0x0002, 0x0003};
[....]
lcd_init();
lcd_putc("** Programmer **");
// Check if the device is an 12F675
if(ISPROG_Read_Device_ID() != ISPROG_UC_675_ID)
{
lcd_gotoxy(1,2);
lcd_putc("! Wrong device !");
lcd_gotoxy(1,3);
printf(lcd_putc, "Device : %4LXh", ISPROG_Read_Device_ID());
lcd_gotoxy(1,4);
printf(lcd_putc, "Rev : %4LXh", ISPROG_Read_Device_Rev());
while(1) {}
}
// Show device number and its revision
lcd_gotoxy(1,2);
lcd_putc("! Device OK !");
lcd_gotoxy(1,3);
printf(lcd_putc, "Device : %4LXh", ISPROG_Read_Device_ID());
lcd_gotoxy(1,4);
printf(lcd_putc, "Rev : %4LXh", ISPROG_Read_Device_Rev());
delay_ms(4000);
lcd_putc("\f** Programmer **");
// Erase all the part
if(ISPROG_Erase_All())
{
// If erased, rewrite the OSCCAL VALUE
// It's not necessary to execute this line if the program is fully programmed
ISPROG_Write_One_Program(ISPROG_osccal_value, ISPROG_OSCCAL_ADDRESS);
// Write bandgap config
ISPROG_Write_ConfigWord((0x3FFF & ISPROG_CONFIG_UTIL_MASK) | (ISPROG_config_word & ISPROG_CONFIG_SAVE_MASK));
lcd_gotoxy(1,2);
printf(lcd_putc, "Erase Ok : %4LXh", ISPROG_osccal_value);
}
else
{
// If the OSCCAL value is incorect, Erase failed
lcd_gotoxy(1,2);
lcd_putc("! Erase Failed !");
while(1) {}
}
// Fill program with incremental value
lcd_gotoxy(1,3);
lcd_putc("P");
ISPROG_Init_Writing();
for(i=0;i<ISPROG_PROG_SIZE;i++)
{
if(!ISPROG_Prog_Writing(i))
{
lcd_gotoxy(1,2);
printf(lcd_putc, "! Erreur : %4LXh", i);
break;
}
}
ISPROG_Stop_Writing();
if(i==ISPROG_PROG_SIZE)
lcd_putc("Ok|");
else
lcd_putc("Er|");
// Fill EEPROM with incremental value
lcd_putc("M");
ISPROG_Init_Writing();
for(i=0;i<ISPROG_EEPROM_SIZE;i++)
{
if(!ISPROG_EEPROM_Writing(i))
{
lcd_gotoxy(1,2);
printf(lcd_putc, "! Erreur : %4LXh", i);
break;
}
}
ISPROG_Stop_Writing();
if(i==ISPROG_EEPROM_SIZE)
lcd_putc("Ok|");
else
lcd_putc("Er|");
// Write the IDlocation word
lcd_putc("ID");
if(ISPROG_Write_All_IDLocation(IDWORD))
lcd_putc("Ok|");
else
lcd_putc("Er|");
// Write the configword
lcd_putc("C");
if(ISPROG_Write_ConfigWord(0x3199))
lcd_putc("Ok");
else
lcd_putc("Er");
// Calculate the checksum
lcd_gotoxy(1,4);
printf(lcd_putc, "Checksum : %4LXh", ISPROG_Checksum());
// In case you protect the device against program read, you must add this line
// to the checksum because the 4 ID are used instead of program aera.
// Checksum = ISPROG_Checksum() + ISPROG_Read_IDLocation(0x00) & 0x000F)<<12 + \
// ISPROG_Read_IDLocation(0x01) & 0x000F)<<8 + \
// ISPROG_Read_IDLocation(0x02) & 0x000F)<<4 + \
// ISPROG_Read_IDLocation(0x03) & 0x000F);
|
The LCD after 1 sec :
Quote: | ** Programmer **
! Device OK !
Device : 0FC0h
Rev : 000Fh |
after 10 sec :
Quote: | ** Programmer **
Erase Ok : 34A5h
POk|MOk|COk|IDOk
Checksum : FB9Ah |
This is just a stupid example. And to verify correctly, I would reset the target after the program step and verify completely (the ICD2 uses this method to prevent PC jump or a bad target reset).
I think with some minor change, this library can be extended to other PIC.
If you change the code or if you find some bugs, please inform me.
@+ Stephanfo
PS : English isn't my native language, so, sorry for my mistakes.
Last edited by Stephanfo on Thu Jun 01, 2006 1:58 am; edited 1 time in total |
|
|
Stephanfo
Joined: 28 Nov 2004 Posts: 5
|
About hardware |
Posted: Thu Jun 01, 2006 1:49 am |
|
|
About the hardware, nothing really important. You can directly connect the master UC I/O to the target UC I/O, except for VPP.
For VPP, you have to provide voltage about 12V ([10V;13V]) to put the taget in PV Mode. This can be done with the following schema.
I add 330 Ohms to prevent short-circuit. And a pull down on VPP (R159) to ensure the return of the target in standby mode.
Any comment, post it .
@+ Stephanfo |
|
|
Storic
Joined: 03 Dec 2005 Posts: 182 Location: Australia SA
|
|
Posted: Thu Jun 01, 2006 4:21 pm |
|
|
I will try your code at some time, as programming a pic from a pic is what I ha been looking for, I was thinking about a bootloader however your methode may be better, (After I program the micro, I wanted to use the RX/TX for communication between the micros for data functions.
(I will be tring the 18F1320 or the 16F87 to be program by a dsPIC or 24F)
ANdrew _________________ What has been learnt if you make the same mistake? |
|
|
ratgod
Joined: 27 Jan 2006 Posts: 69 Location: Manchester, England
|
|
Posted: Mon Sep 17, 2007 8:59 pm |
|
|
do you know how to use this to program chips such as PIC18F2520, 2550 and 2580? or maybe the PIC16F877A?
many thanks |
|
|
nuno12345
Joined: 16 Jul 2008 Posts: 50
|
|
Posted: Thu Jun 25, 2009 11:19 am |
|
|
Hello, old thread but as anyone tested this?
Do we really need BC856/BC846 or can we use BC556/BC546? |
|
|
Ln_mark7930
Joined: 06 Mar 2009 Posts: 21
|
Where find PIC info? |
Posted: Tue Nov 03, 2009 10:53 am |
|
|
Where Can I find Information about:
ISPROG_OSCCAL_ADDRESS
ISPROG_CONFIG_ADDRESS
ISPROG_CONFIG_UTIL_MASK
ISPROG_CONFIG_SAVE_MASK ???
Inside datasheet of microchip there are not information about this data.
I test the code with one 12F629 and its work perfectly, but if I try to recompile the code to trasfert it inside a 12F683 it doesn't work because register are wrong.
Someone can help me? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 03, 2009 1:06 pm |
|
|
Quote: |
Where can I find information about:
ISPROG_OSCCAL_ADDRESS
|
Look in this section of the 12F629 data sheet. It's given in the sample code:
Quote: | EXAMPLE 9-1: CALIBRATING THE
INTERNAL OSCILLATOR
|
Quote: |
Where can I find information about:
ISPROG_CONFIG_ADDRESS
|
Look in the title of this section (at the lsb):
Quote: |
REGISTER 9-1: CONFIG — CONFIGURATION WORD (ADDRESS: 2007h) |
Quote: |
Where can I find information about:
ISPROG_CONFIG_UTIL_MASK
|
Look at the bit diagram of the Config Word in this section. Notice that
it has 9 contiguous bits on the right side of the word. The bitmask for
these bits (in hex) is 0x1FF.
Quote: |
REGISTER 9-1: CONFIG — CONFIGURATION WORD (ADDRESS: 2007h)
|
Quote: |
Where can I find information about:
ISPROG_CONFIG_SAVE_MASK
|
Again, look at the Config Word in this section. The two "Bandgap" bits
on the left of the bit diagram are determined by the Microchip factory
during chip testing. You don't want to change those bits. You want
to save them from changes. The bitmask for those bits is 0x3000.
Quote: |
REGISTER 9-1: CONFIG — CONFIGURATION WORD (ADDRESS: 2007h)
|
For more information, look in the Programming Specification for the
12F629:
http://ww1.microchip.com/downloads/en/DeviceDoc/41191D.pdf
It also gives the addresses for the OSCCAL byte, the data eeprom
address, and the Device ID values (you can see the bitmask for the
Device ID by looking at the bit range). |
|
|
Ln_mark7930
Joined: 06 Mar 2009 Posts: 21
|
I need help with 18f2520 |
Posted: Fri Jun 11, 2010 6:50 am |
|
|
Hi boys,
I need to edit the original firmware from 12f629 to 18f2520.
I see the 18f2xxx Programming Specification and I see that the program mode is different.
Have someone the final code for PIC18f2520 or similar???
Thanks at all.
Mark |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|