When you’re using external crystal oscillator for an AVR based Atmel MCU, you need to change the High Fuse Byte and the Low Fuse Byte in order to disable internal oscillator of the MCU and to enable the use of external oscillator. Not only that, these fuse bits could be used in other options too. These things you could find out by reading the specific datasheet of the MCU.
So what happens if you program these fuse bits in a wrong way is, you may be unable to program the MCU again and therefore the entire MCU will be useless. There’s a way to correct the fuse bits using high voltage programming. In high voltage programming method, 12V input will be given to the Reset pin of the MCU.
When you’re creating the circuit, make sure that you have a common ground and NOT a common +5V (even if you regulate the 12V to 5V for some reason) between arduino and the rest of your circuit. If you regulate the 12V to 5V and make it common with arduino’s 5V, it may damage your arduino and the computer.
Here we’re using Atmega328P MCU as the MCU which needs to be rescued and a Arduino DUE. This code should be working fine with Arduino MEGA version. Please read the datasheet of the MCU before continuing.
Required Components
- Arduino DUE (or MEGA)
- 1kΩ resistors (20 of them)
- LED
- Jumper wires
- Atmega 328p MCU
- 12V DC power supply
- BC338 or 2N3904 Transistor (or any NPN transistor)
- Push Button
- Breadboard
Circuit Diagram


Each input pin between Arduino and Atmega328p MCU is protected with a 1kΩ resistor. If you don’t need protection, these resistors could be removed. Please make sure all components are connected correctly before you turn ON power.
Code
Before uploading the code into the Arduino, find the default High Fuse Byte and the Low Fuse Byte for the MCU by reading the datasheet and replace the value of HFUSE and LFUSE with them.
#define HFUSE 0xD9 #define LFUSE 0x62 void setup() { //Power pinMode(22, OUTPUT); //VCC & AVCC digitalWrite(22, LOW); pinMode(23, OUTPUT); //PD4 digitalWrite(23, LOW); pinMode(24, OUTPUT); //PD3 digitalWrite(24, LOW); pinMode(25, OUTPUT); //PD2 digitalWrite(25, LOW); pinMode(26, INPUT); //PD1 digitalWrite(26, LOW); pinMode(27, OUTPUT); //PD5 digitalWrite(27, LOW); pinMode(28, OUTPUT); //RESET digitalWrite(28, HIGH); pinMode(29, INPUT); //BUTTON) digitalWrite(29, HIGH); pinMode(30, OUTPUT); //PC2 digitalWrite(30, LOW); pinMode(31, OUTPUT); //PB6 digitalWrite(31, LOW); pinMode(32, OUTPUT); //PD6 digitalWrite(23, LOW); pinMode(33, OUTPUT); //PD7 digitalWrite(33, LOW); pinMode(34, OUTPUT); //PB0 digitalWrite(34, LOW); pinMode(35, OUTPUT); //PB1 digitalWrite(35, LOW); pinMode(36, OUTPUT); //PB2 digitalWrite(36, LOW); pinMode(37, OUTPUT); //PB3 digitalWrite(37, LOW); pinMode(38, OUTPUT); //PB4 digitalWrite(38, LOW); pinMode(39, OUTPUT); //PB5 digitalWrite(39, LOW); pinMode(40, OUTPUT); //PC0 digitalWrite(40, LOW); pinMode(41, OUTPUT); //PC1 digitalWrite(41, LOW); } void progHFUSE(){ //Send Command digitalWrite(32, HIGH); digitalWrite(27, LOW); digitalWrite(23, LOW); for(int i = 34; i <= 41; i++){ if(i == 40){ digitalWrite(i, HIGH); }else{ digitalWrite(i, LOW); } } digitalWrite(31, HIGH); delay(1); digitalWrite(31, LOW); delay(1); //Write Fuse digitalWrite(32, LOW); digitalWrite(27, HIGH); delay(1); for(int i = 34; i <= 41; i++){ if(HFUSE & (1 << (i - 34))){ digitalWrite(i, HIGH); }else{ digitalWrite(i, LOW); } } digitalWrite(31, HIGH); delay(1); digitalWrite(31, LOW); digitalWrite(23, HIGH); digitalWrite(24, LOW); delay(1); digitalWrite(24, HIGH); delay(100); } void progLFUSE(){ //Send Command digitalWrite(32, HIGH); digitalWrite(27, LOW); digitalWrite(23, LOW); for(int i = 34; i <= 41; i++){ if(i == 40){ digitalWrite(i, HIGH); }else{ digitalWrite(i, LOW); } } digitalWrite(31, HIGH); delay(1); digitalWrite(31, LOW); delay(1); //Write Fuse digitalWrite(32, LOW); digitalWrite(27, HIGH); delay(1); for(int i = 34; i <= 41; i++){ if(LFUSE & (1 << (i - 34))){ digitalWrite(i, HIGH); }else{ digitalWrite(i, LOW); } } digitalWrite(31, HIGH); delay(1); digitalWrite(31, LOW); digitalWrite(23, LOW); digitalWrite(24, LOW); delay(1); digitalWrite(24, HIGH); delay(100); } void loop(){ while (digitalRead(29)) {} digitalWrite(50, HIGH); digitalWrite(48, LOW); // Initialize pins to enter programming mode digitalWrite(33, LOW); digitalWrite(32, LOW); digitalWrite(30, LOW); digitalWrite(27, LOW); digitalWrite(23, LOW); // Enter programming mode digitalWrite(22, HIGH); digitalWrite(24, HIGH); digitalWrite(25, HIGH); delay(1); digitalWrite(28, LOW); delay(1); // Program HFUSE progHFUSE(); // Program LFUSE progLFUSE(); delay(1000); // Exit programming mode digitalWrite(28, HIGH); // Turn off outputs for(int i = 34; i <= 41; i++){ digitalWrite(i, LOW); } digitalWrite(22, LOW); digitalWrite(24, LOW); digitalWrite(25, LOW); digitalWrite(27, LOW); digitalWrite(23, LOW); digitalWrite(33, LOW); digitalWrite(32, LOW); digitalWrite(30, LOW); }
Now upload the code and give power to the circuit. If the circuit is correct, the LED will turn ON. Now press the push button so the LED will be turned off. Now wait for LED to turn back ON again. This might take a few seconds. Now the fuse should be corrected. Try uploading a program to the MCU to verify.
Please use these references if you need to learn more about rescuing fuse bits.
http://www.instructables.com/id/AVR-High-voltage-programming-Fuses-rescue/?ALLSTEPS
http://denki.world3.net/avr_rescue.html
If you have any questions or ideas to improve this article, please send them to our official e-mail address or comment below.