Мастерская Уэйна

Сброс предохранителя ATTiny при помощи Arduino


sites.google.com/site/wayneholder/attiny-fuse-reset


Примечание: для обновленной версии этого проекта см. «ATTiny Fuse Reset with 12 Volt Charge Pump»(https://sites.google.com/site/wayneholder/attiny-fuse-reset-with-12-volt-charge-pump), в котором добавлен встроенный 12-вольтный источник питания.

Мне нравится работать с микроконтроллерами Atmel серии ATTiny, и время от времени я ошибаюсь и «блокирую» один из них, устанавливая значение предохранителя на то, что запрещает дальнейшее перепрограммирование чипа с помощью моего программатора AVR ISP MKII. Выход из этого тупика - использовать программатор высокого напряжения, но, поскольку у меня его нет, я искал другое решение. Мое спасение пришло из страницы Пола Уиллоуби, который описывает, как он построил программатор высоковольтных предохранителей, используя несколько резисторов, один транзистор 2N3904 NPN, источник питания 12 В (я использовал 8 батареек AAA, но батарея A23 была бы более элегантным решением. ) и Arduino. Проведя небольшое исследование, чтобы выяснить, как работает его код, я добавил несколько улучшений, таких как возможность читать подпись устройства и использовать ее для сброса предохранителей на правильные заводские настройки по умолчанию для каждого устройства. Результат показан ниже.

Если вы хотите использовать этот код, начните с создания простой схемы Пола на плате Arduino Protoboard. Вот моя версия необходимого набора схем для перепрограммирования ATTiny13 (или другого 8-контактного ATTiny, такого как серия ATTiny25-45-85). Такая же конструкция будет работать и с 14-контактными ATTiny24-44-84, но подключение контактов к устройству будет другим.

FuseResetBat.png

Затем вы можете добавить 8 батарей или подключить лабораторный источник питания для подачи необходимых 12 вольт. Затем загрузите скетч (есть ссылка для загрузки внизу страницы), подключите устройство ATTiny, которое требует исправления предохранителей (см. Список поддерживаемых устройств в исходном коде), откройте Serial Monitor в Arduino IDE и выберите 19200 бод в качестве последовательной скорости. Затем отправьте символ в Arduino, используя кнопку «отправить» последовательного монитора, чтобы запустить цикл сброса предохранителя. Код распечатает подпись устройства и до и после значений предохранителей и, что это. Теперь у вас должен быть работающий ATTiny!

=======================================================================================================
    // 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/
    //
    // Fuse Calc:
    //   http://www.engbedded.com/fusecalc/

    #define  RST     13    // Output to level shifter for !RESET from transistor
    #define  SCI     12    // Target Clock Input
    #define  SDO     11    // Target Data Output
    #define  SII     10    // Target Instruction Input
    #define  SDI      9    // Target Data Input
    #define  VCC      8    // Target VCC

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

    // Define 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

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

    void loop() {
       if (Serial.available() > 0) {
        Serial.read();
        pinMode(SDO, OUTPUT);     // Set SDO to output
        digitalWrite(SDI, LOW);
        digitalWrite(SII, LOW);
        digitalWrite(SDO, LOW);
        digitalWrite(RST, HIGH);  // 12v Off
        digitalWrite(VCC, HIGH);  // Vcc On
        delayMicroseconds(20);
        digitalWrite(RST, LOW);   // 12v On
        delayMicroseconds(10);
        pinMode(SDO, INPUT);      // Set SDO to input
        delayMicroseconds(300);
        unsigned int sig = readSignature();
        Serial.print("Signature is: ");
        Serial.println(sig, HEX);
        readFuses();
        if (sig == ATTINY13) {
          writeFuse(LFUSE, 0x6A);
          writeFuse(HFUSE, 0xFF);
        } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
                   sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) {
          writeFuse(LFUSE, 0x62);
          writeFuse(HFUSE, 0xDF);
          writeFuse(EFUSE, 0xFF);
        }
        readFuses();
        digitalWrite(SCI, LOW);
        digitalWrite(VCC, LOW);    // Vcc Off
        digitalWrite(RST, HIGH);   // 12v Off
      }
    }

    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 () {
      byte val;
            shiftOut(0x04, 0x4C);  // LFuse
            shiftOut(0x00, 0x68);
      val = shiftOut(0x00, 0x6C);
      Serial.print("LFuse: ");
      Serial.print(val, HEX);
            shiftOut(0x04, 0x4C);  // HFuse
            shiftOut(0x00, 0x7A);
      val = shiftOut(0x00, 0x7E);
      Serial.print(", HFuse: ");
      Serial.print(val, HEX);
            shiftOut(0x04, 0x4C);  // EFuse
            shiftOut(0x00, 0x6A);
      val = shiftOut(0x00, 0x6E);
      Serial.print(", EFuse: ");
      Serial.println(val, HEX);
    }

    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;
    }


==============================================================================================