sbinder
Published © GPL3+

ATtiny85 Powered High Voltage AVR Programmer

This very simple and inexpensive circuit will reset the fuses on a bricked ATtiny chip. Once programmed, no Arduino is required!

BeginnerFull instructions provided30 minutes21,737
ATtiny85 Powered High Voltage AVR Programmer

Things used in this project

Hardware components

ATtiny85
Microchip ATtiny85
×1
Linear Regulator (7805)
Linear Regulator (7805)
Almost any 5v voltage regulator will do.
×1
General Purpose Transistor NPN
General Purpose Transistor NPN
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 330 ohm
Resistor 330 ohm
×1
5 mm LED: Red
5 mm LED: Red
×1
12v DC Power Source
×1

Story

Read more

Schematics

Fuse Resetter for 8-pin chips

This circuit resets the 8-pin ATTiny chips. Schematic for the 14-pin version is below.

8-pin Schematic

This circuit is for the 8-pin ATTiny chips. Schematic for the 14-pin chips is below.

14-pin Schematic

This circuit is for resetting the 14-pin ATTiny chips.

Code

ATTiny85 Powered High Voltage AVR Programmer

C/C++
Load this sketch onto the "Master" ATTiny85. It can then be used to reset the fuses on many ATTiny chips.
// AVR High-voltage Serial Fuse Reprogrammer
// Adapted from code and design by Paul Willoughby 03/20/2010
//   http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
// and Wayne Holder 
//   https://sites.google.com/site/wayneholder/attiny-fuse-reset
//
// Fuse Calc:
//   http://www.engbedded.com/fusecalc/

#define  LED      3    // Status indicator LED
#define  RST      4    // (13) Output to level shifter for !RESET from transistor
#define  SCI      3    // (12) Target Clock Input
#define  SDO      2    // (11) Target Data Output
#define  SII      1    // (10) Target Instruction Input
#define  SDI      0    // ( 9) Target Data Input

#define  HFUSE  0x747C
#define  LFUSE  0x646C
#define  EFUSE  0x666E

// ATTiny series signatures
#define  ATTINY13   0x9007  // L: 0x6A, H: 0xFF             8 pin
#define  ATTINY24   0x910B  // L: 0x62, H: 0xDF, E: 0xFF   14 pin
#define  ATTINY25   0x9108  // L: 0x62, H: 0xDF, E: 0xFF    8 pin
#define  ATTINY44   0x9207  // L: 0x62, H: 0xDF, E: 0xFFF  14 pin
#define  ATTINY45   0x9206  // L: 0x62, H: 0xDF, E: 0xFF    8 pin
#define  ATTINY84   0x930C  // L: 0x62, H: 0xDF, E: 0xFFF  14 pin
#define  ATTINY85   0x930B  // L: 0x62, H: 0xDF, E: 0xFF    8 pin

int error = 0;
byte FuseH = 0;
byte FuseL = 0; 
byte FuseX = 0;

void setup() {
  pinMode(RST, OUTPUT);
  digitalWrite(RST, HIGH);  // Level shifter is inverting, this shuts off 12V
  pinMode(SDI, OUTPUT);
  pinMode(SII, OUTPUT);
  pinMode(SCI, OUTPUT);
  pinMode(SDO, OUTPUT);     // Configured as input when in programming mode

  digitalWrite(SDI, LOW);
  digitalWrite(SII, LOW);
  digitalWrite(SDO, LOW);

  delayMicroseconds(30);  // wait long enough for target chip to see rising edge
  digitalWrite(RST, LOW);  // 12v On
  delayMicroseconds(10);
  pinMode(SDO, INPUT);      // Set SDO to input
  delayMicroseconds(300);
  unsigned int sig = readSignature();

  if (sig == ATTINY13) {
    writeFuse(LFUSE, 0x6A);
    writeFuse(HFUSE, 0xFF);
    readFuses();    // check to make sure fuses were set properly
    if (FuseL != 0x6A || FuseH != 0xFF) {
      error = 5;    // fast flash if fuses don't match expected
    }
  } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
             sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) {
    writeFuse(LFUSE, 0x62);
    writeFuse(HFUSE, 0xDF);
    writeFuse(EFUSE, 0xFF);
    readFuses();    // check to make sure fuses were set properly    
    if (FuseL != 0x62 || FuseH != 0xDF || FuseX != 0xFF) {
      error = 5;    // fast flash if fuses don't match expected
    }
  } else {    
    error = 1;      // slow flash if device signature is invalid
  }

  digitalWrite(SCI, LOW);
  digitalWrite(RST, HIGH);   // 12v Off
  digitalWrite(LED, LOW);    // LED off for succerss
}

void loop() {
  // Flash LED if there was an error
  while (error > 0) {
    int d = 500 / error;
    digitalWrite(LED, HIGH);
    delay(d);
    digitalWrite(LED, LOW);
    delay(d);
  }
}

byte shiftOut (byte val1, byte val2) {
  int inBits = 0;
  //Wait until SDO goes high
  while (!digitalRead(SDO))
    ;
  unsigned int dout = (unsigned int) val1 << 2;
  unsigned int iout = (unsigned int) val2 << 2;
  for (int ii = 10; ii >= 0; ii--)  {
    digitalWrite(SDI, !!(dout & (1 << ii)));
    digitalWrite(SII, !!(iout & (1 << ii)));
    inBits <<= 1;
    inBits |= digitalRead(SDO);
    digitalWrite(SCI, HIGH);
    digitalWrite(SCI, LOW);
  }
  return inBits >> 2;
}

void writeFuse (unsigned int fuse, byte val) {
  shiftOut(0x40, 0x4C);
  shiftOut( val, 0x2C);
  shiftOut(0x00, (byte) (fuse >> 8));
  shiftOut(0x00, (byte) fuse);
}

void readFuses () {
  shiftOut(0x04, 0x4C);  // LFuse
  shiftOut(0x00, 0x68);
  FuseL = shiftOut(0x00, 0x6C);

  shiftOut(0x04, 0x4C);  // HFuse
  shiftOut(0x00, 0x7A);
  FuseH = shiftOut(0x00, 0x7E);

  shiftOut(0x04, 0x4C);  // EFuse
  shiftOut(0x00, 0x6A);
  FuseX = shiftOut(0x00, 0x6E);
}

unsigned int readSignature () {
  unsigned int sig = 0;
  byte val;
  for (int ii = 1; ii < 3; ii++) {
    shiftOut(0x08, 0x4C);
    shiftOut(  ii, 0x0C);
    shiftOut(0x00, 0x68);
    val = shiftOut(0x00, 0x6C);
    sig = (sig << 8) + val;
  }
  return sig;
}

Credits

sbinder

sbinder

1 project • 3 followers

Comments