Ciao a tutti
Sto pensando di costruirne uno con un ATmega328P come programmatore, che controlli anche un LCD su cui mostrare le opzioni. Per fare ciò, vorrei mettere delle resistenze (220 ohm?) in serie a PD0...PD7 che inviano i dati a PB0...PC1 e collegare l'LCD su PD0...PD5.
Finita l'impostazione, inizia la programmazione, con il display che rimane collegato in lettura sui dati.
Le resistenze servono solo nel caso che il microcontrollore da reimpostare abbia attivo il clock interno e un programma caricato che attivi PB0...PC1.
Dovrebbe funzionare... Che ne pensate?
Grazie
Gianluca
Nota: il pulsante SEL non lo monterò.
/*
HVFuse - Use High Voltage Programming Mode to Set Fuses on ATmega328
09/23/08 Jeff Keyzer http://mightyohm.com
The HV programming routines are based on those described in the
ATmega48/88/168 datasheet 2545M-AVR-09/07, pg. 290-297
This program should work for other members of the AVR family, but has only
been verified to work with the ATmega168. If it works for you, please
let me know! http://mightyohm.com/blog/contact/
*/
// Desired fuse configuration
#define HFUSE 0xD9 // Default for ATmega328, for others see // ELECTROPEPPER CHANGED THIS LINES
#define LFUSE 0x62 // http://www.engbedded.com/cgi-bin/fc.cgi //
/*
Pin I/O Port Funzione
2 0 PD0 Data0 | RS
3 1 PD1 Data1 | EN L
4 2 PD2 Data2 | D4 C
5 3 PD3 Data3 | D5 D
6 4 PD4 Data4 | D6
11 5 PD5 Data5 | D7
12 6 PD6 Data6
13 7 PD7 Data7
14 8 PB0 VCC
15 9 PB1 BS1
16 10 PB2 WR
17 11 PB3 OE
18 12 PB4 RDY
19 13 PB5 XA0
23 14 A0 PC0 RST
24 15 A1 PC1 Pulsante
25 16 A2 PC2 BS2
26 17 A3 PC3 XTAL1
27 18 A4 PC4 XA1
28 19 A5 PC5 PAGEL
*/
// Pin Assignments
#define VCC 8
#define RDY 12 // RDY/!BSY signal from target
#define OE 11
#define WR 10
#define BS1 9
#define XA0 13
#define XA1 18 // Analog inputs 0-5 can be addressed as
#define PAGEL 19 // digital outputs 14-19
#define RST 14 // Output to level shifter for !RESET
#define BS2 16
#define XTAL1 17
#define PULSANTE 15 // Start button
const char *percorso=__FILE__; // Dalla macro __FILE__ prende il percorso del file in uso. Questa parte di programma,
char ver[12]; // però, si trova nel file/cartella dell'IDE c_setup, in cui non è scritta la versione
// del programma. La versione è scritta nel file principale, che ha lo stesso nome della
// cartella che contiene tutti i file del programma. Questa riga, quindi, non può stare
// nel setup.
#include <LiquidCrystal.h>
LiquidCrystal lcd(0,1,2,3,4,5); // RS,EN,D4,D5,D6,D7
uint32_t t_premuto; // millis() alla pressione del pulsante.
uint8_t prg=0; // Numero del programma selezionato.
uint8_t lfuse;
uint8_t hfuse;
uint8_t xfuse;
uint8_t stato=0;
void setup() // run once, when the sketch starts
{
pinMode(0, OUTPUT); // LCD RS
pinMode(1, OUTPUT); // LCD EN
pinMode(2, OUTPUT); // LCD D4
pinMode(3, OUTPUT); // LCD D5
pinMode(4, OUTPUT); // LCD D6
pinMode(5, OUTPUT); // LCD D7
pinMode(A1, INPUT_PULLUP);
pinMode(VCC, OUTPUT);
pinMode(RDY, INPUT);
pinMode(OE, OUTPUT);
pinMode(WR, OUTPUT);
pinMode(BS1, OUTPUT);
pinMode(XA0, OUTPUT);
pinMode(XA1, OUTPUT);
pinMode(PAGEL, OUTPUT);
pinMode(RST, OUTPUT); // Signal to level shifter for +12V !RESET.
digitalWrite(RST, HIGH); // Level shifter is inverting: this shuts off 12V.
pinMode(BS2, OUTPUT);
pinMode(XTAL1, OUTPUT);
lcd.print(F(" Fuse Rescue GG "));
lcd.setCursor(2,1); lcd.print("LF");
lcd.setCursor(7,1); lcd.print("HF");
lcd.setCursor(11,1); lcd.print("Ext");
delay(1000);
}
#define PREMUTO !(PINC&0b000000010) // Pulsante su PC1 (A1).
void loop()
{
t_premuto=millis(); // Prende il tempo.
while(PREMUTO) // Pressione lunga: programmazione.
{
if(millis()-t_premuto>3000)
{
lcd.setCursor(0,0); lcd.print(F("*PROGRAMMAZIONE*"));
programma();
lcd.setCursor(0,0); lcd.print(F(" *** FATTO! *** "));
stato=0;
}
}
if (!PREMUTO) stato=0; // Attesa.
else if(PREMUTO) stato=1; // Incrementa prg.
if(stato==1)
{
prg++;
lcd.setCursor(0,0); lcd.print(prg); // Numero progressivo.
lcd.setCursor(2,0);
switch(prg)
{
case 1:
lcd.print(F("328P 16MHZ BL "));
lfuse=0xFF; hfuse=0xFD; xfuse=0xDF;
display_fuse();
break;
case 2:
lcd.print(F("328P 16MHZ BL "));
lfuse=0xFF; hfuse=0xFD; xfuse=0xDF;
display_fuse();
break;
case 3:
lcd.print(F("328P 16MHZ BL "));
lfuse=0xFF; hfuse=0xFD; xfuse=0xDF;
display_fuse();
break;
case 4:
lcd.print(F("328P 16MHZ BL "));
lfuse=0xFF; hfuse=0xFD; xfuse=0xDF;
display_fuse();
break;
}
stato=0;
}
}
void display_fuse()
{
lcd.setCursor(0,1);
lcd.print(lfuse,HEX); lcd.print(hfuse,HEX); lcd.print(xfuse,HEX);
}
void sendcmd(byte command) // Send command to target AVR.
{
// Set controls for command mode:
digitalWrite(XA1, HIGH);
digitalWrite(XA0, LOW);
digitalWrite(BS1, LOW);
//DATA = B01000000; // Command to load fuse bits
PORTD = command;
digitalWrite(XTAL1, HIGH); // pulse XTAL to send command to target.
delay(1);
digitalWrite(XTAL1, LOW);
//delay(1);
}
void writefuse(byte fuse, boolean highbyte) // write high or low fuse to AVR.
{
// if highbyte = true, then we program HFUSE, otherwise LFUSE.
// Enable data loading:
digitalWrite(XA1, LOW);
digitalWrite(XA0, HIGH);
delay(1);
// Write fuse:
PORTD = fuse; // set desired fuse value.
digitalWrite(XTAL1, HIGH);
delay(1);
digitalWrite(XTAL1, LOW);
if(highbyte == true) digitalWrite(BS1, HIGH); // program HFUSE.
else digitalWrite(BS1, LOW);
digitalWrite(WR, LOW);
delay(1);
digitalWrite(WR, HIGH);
delay(100);
}
void programma()
{
// Set up control lines for HV parallel programming.
PORTD = 0x00; // Clear digital pins 0-7.
DDRD = 0xFF; // set digital pins 0-7 as outputs.
// Initialize pins to enter programming mode:
digitalWrite(PAGEL, LOW);
digitalWrite(XA1, LOW);
digitalWrite(XA0, LOW);
digitalWrite(BS1, LOW);
digitalWrite(BS2, LOW);
// Enter programming mode
digitalWrite(VCC, HIGH); // Apply VCC to start programming process.
digitalWrite(WR, HIGH); // Now we can assert !OE and !WR.
digitalWrite(OE, HIGH);
delay(1);
digitalWrite(RST, LOW); // Apply 12V to !RESET thru level shifter.
delay(1);
// Now we're in programming mode until RST is set HIGH again.
// Firstly we program HFUSE:
sendcmd(B01000000); // Send command to enable fuse programming mode
writefuse(HFUSE, true);
// Now we program LFUSE:
sendcmd(B01000000);
writefuse(LFUSE, false);
delay(1000); // wait a while to allow button to be released
// Exit programming mode:
digitalWrite(RST, HIGH);
// Turn off all outputs:
PORTD = 0x00;
digitalWrite(OE, LOW);
digitalWrite(WR, LOW);
digitalWrite(PAGEL, LOW);
digitalWrite(XA1, LOW);
digitalWrite(XA0, LOW);
digitalWrite(BS1, LOW);
digitalWrite(BS2, LOW);
digitalWrite(VCC, LOW);
}