Fuses are among the most difficult topics that i encountered whilst learning about programming microcontrollers. Even after searching and reading extensively, i still could not manage to clear my concepts about them. But then i started learning about them taking one at a time. This helped immensely. In this instructable, I will try to provide ample information about this topic. This is my first instructable, please point out my mistakes so that i can improve.
Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.
Step 1: What Are Fuses ?
When we start learning about fuse settings, the fundamental question which arises in our minds is- What exactly are fuses ? and why do we need to bother to learn them ?
I hope that this instructable will help to find an answer to this question.
To begin with, AVR MCUs have, in general, three memory areas:
1) FLASH, which is dedicated to program code.
2) SRAM, which is used for run-time variables.
3) EEPROM, which can be used by user code to store data that have to be preserved when MCU is turned off.
4) Now, the fuses form a fourth memory area available for programming. This holds a few bytes that contain those bits.
To put it simply, fuses are a part of the microcontroller's memory which is reserved for certain functions which decides the way the microcontroller will work.To be precise, the fuse is a reserved section of EEPROM memory in a microcontroller. EEPROM stands for Electrically Erasable Programmable Read Only Memory. The EEPROM is a non-volatile form of memory. Non-volatile means, once stored, the memory is retained even after the power is turned off. A fuse is an EEPROM bit that controls low level features and pin assignments. Fuses are not accessible by the program, they can only be changed by a chip programmer. I will explain later by what i mean by low level features. As i said, fuse settings once done cannot be used by the program in any way, it means a program running in the microcontroller chip cannot alter the fuse settings. Even if you are using a "self-programming" microcontroller i.e. a microcontroller that allows bootloader software running on it to upload the program to its flash memory, u cannot alter the fuse bits.
Though i am browsing over the whole topic in brief, i mainly intend to show- how to set fuses for an avr microcontroller to run it with an external clock.
Step 2: Why Are Programming Fuses Nescessary?
Fuses controls the way the microcontroller works, so changing the fuse settings enables us to change and modify the microcontroller as per our requirements. There are few parameters in the chip which are used to configure it, before it can be used for external environment. These parameters are set with the use of Fuse Bits. In other words, the fuse bit determines the behavior of the chip, whether it has a boot loader, what is the speed and voltage it runs at, the Watchdog Timer conditions, memory protection modes, start up options, clock source and divider, programming options,brown-out detection etc.
The main advantage of fuse bits is thus clear, that the microcontroller can be configured as per the need of the situation. There is no way to change the clock behavior through the program code. Fuse bits differ greatly between different AVR variants.
Step 3: How to Program Fuses ?
Before starting, we need to look up at the fuse bits of Atmega8 and initial value of them. Since im making this instructable from mobile, i made a table containing the required details. I created it using google sheet android app. I coudn't find a way to convert them to pictures. So here im posting the link.
Fuse bits of Atmega 8 ( the one im using in this tutorial)
Now we move on to the details of how to program the fuse bits in your AVR depending on the particular programmer you are using. At first we should consult the manual of the programmer about the details. For instance, if you are using an STK600 with AVR Studio, the STK600 window has a tab labeled Fuses, where you set the different bits and where you can program, verify or read the fuse bits.
(I am using an Atmega 8 for my example. I mostly use Atmega 8 as it is cheap and contains enough memory for most of my projects).
Most people have confusion regarding this topic. To put it very simply, there are only two types of fuses, high fuse (hfuse) and low fuse (lfuse), some microcontrollers have an additional fuse byte known as extended fuse (efuse).
The most confusing part comes here. The unprogrammed state of a fuse bit is logic high or 1, programming any fuse bit will change its level to logic low or 0.
"An exception just to keep in mind is- the fuse bits related to boot loader are not accessible from software, but, these can be accessed in programming mode using parallel /serial programming tool."
As described in the picture above, the fuse along with its bit value and bit number is shown. Some functions of the the above mentioned fuses are :-
(I used a Atmega 8 datasheet for for the diagram which i posted).
High Fuse byte (hfuse)
1) First bit is BOOTRST which is unprogrammed by default (1). If this bit is programmed (0) then after powering up or device reset it starts program executing from bootloader memory section. Simply, if a bootlaoder is used to flash MCU, this bit must be enabled. If you simply upload your firmware using ISP programmer, then leave this bit untouched.
BOOTSZ0 and BOOTSZ1 are also important if bootloader is used. These bits allows to select bootloader section size.
2) Next bit is EESAVE. If this fuse is programmed (by writing 0 to it) EEPROM memory stays untouched during Chip Erase procedure. Sometimes this fuse may be helpful. For instance if you keep some important data in EEPROM memory like calibration values and need to update program without loosing this data, then program this bit. But if you want always have clean chip after erase, then leave this bit untouched (set to 1).
3) WDTON bit is used to initially set watchdog timer. If you program this your watchdog timer will be forced to be always on and keep resetting chip periodically if no special care is taken. If no need for watchdog, then leave it unprogammed.
4) SPIEN bit is used to disable serial programming mode ISP. Actually it is not possible to disable this bit from serial mode. It has to be done through high voltage programming.
5) Same situation is with RSTDSBL bit. It is used to disable reset functionality that converts RESET pin in to I/O. In general this is not recommended. And it cannot be disabled when device is programmed in ISP mode.
6) CKOPT bit is used to select oscillator options.
Low fuses (lfuse)
Lets looks at low byte of fuses.
1) A group of four similar bits which are CKSEL0 to CKSEL3 are used to select clocking options. By default CKSEL0 to CKSEL3 fuses are set to select internal 8MHz RC oscillator. But we know AVRs can be clocked in more different ways:
* Calibrated internal RC oscillator (default 8MHz)
* External RC oscillator
* External crystal or crystal resonator
* External low-frequency crystal
* External clock signal source
I have explained about SUT(start up time) in the next step.
I would be writing about how to calculate these values on our own, later in this instructable.
2) BODEN or brown out detection enable bit enables brown out detection. Brown out detection is generally disabled (1). Programming this bit low (0) enanbles brown out detection. The reason for this feature is that- when the supply voltage gets lower than the voltage required by the microcontroller, it starts behaving erratically. It may start erasing its own memory or may run random sections from its flash. To avoid this, brown out detection feature has been provided. Once the supply voltage gets lower than the set BOD level, the chip will switch of safely. When the supply voltage again returns to normal, the chip starts over again.
BODLEVEL- With this bit we can set the Brown Out Detection level. For example- if the microcontroller run on 3.3 volts, we can set the Brown Out Detection level at 2.7 volts, so that if the supply voltage becomes lower than this then the microcontroller will shut down safely.
An interesting feature to note here is, other AVR microcontrollers like Atmega 32 have some fuses different like in the high fuse byte they have OCDEN and JTAGEN and in Atmega 328p there are DWEN etc.
I apologise for the low quality pictures because i am making this instructable from my android.
Step 4: An Insight to Clocks and Oscillators.
Yes its true that there are plenty of fuse calculator apps available on the internet. But i personally dont feel like using it before learning thoroughly about the topic. Now its the time to learn about the way to program fuse bits on our own. I will write how to select and change different clock features according to our needs. Before that we need to learn about a few terms related to this topic before we start programming.
What is a clock ?
A clock is simply a device that keeps track of time, it kind of gives you a beat to move to. The clock on the wall counts in increments of seconds, for example. A metronome for your instrument might give you a beat every half or full second. The amount of times a clock ticks(cycles per second) is called its frequency, its measured in Hertz (Hz or cycles/second). Similarly, the Atmega has a clock inside too, and its speed directly relates to how many instructions it can carry out per second (on every tick/cycle of the clock). The default clock speed that comes with most AVRs is 1 MHz (1 million cycles per second).
The only disadvntage with the internal oscillator is that its frequency changes with the applied voltage and with temperature which is not the case in other clock sources.
How can we set a clock speed?
We have two options:
Use the internal one, or use an external source. If we are writing a code that does basic stuff, and doesn't require precision timing, the internal clock should suffice. In any other case, particularly for communication (i.e. using the UART for example), timing is critical. In that case, we need an alternate method, so we use things like crystals, resonators, oscillators, and clocks. They are all suitable to produce the beat we are looking for, at the frequency we are looking for, but the most common amongst hobbyists are crystals and resonator. We will be using a crystal for this tutorial.
To use the crystal we will also require two ceramic 18-22 pF capacitors. A resonator, on the other hand, has the capacitors and crystal built into one package, thus making it a little more compact. That’s pretty much only the difference, but there may be subtle differences in setting fuse bits if a resonator is being used. Oscillators require an external power source to operate, and usually have four pins.
Start-up time (SUT)
Clock sources usually need a little bit of time to warm up and start giving us a reliable signal when the microcontroller is turned on. This is called the start-up time.
Step 5: Programmimg the Clock Fuse on Our Own!
You have already got a rough basic idea about fuse bytes and how they work and what are their functions in a microcontroller (here Atmega 8). Now, we are moving on the programming stage. I mostly use Winavr for this purpose, so i wont be able to tell, how it can be done using extreme burner and others.
We now know that we have to change CKOPT ( bit number 4) from high fuse byte and change values of CKSEL0, CKSEL1,CKSEL2,CKSEL3 and SUT0, SUT1 from low fuse byte because these are the bits which control the clock settings. Since we are only configuring the clock settings, other fuse settings will be left as it is. If other fuse bit values are changed even by mistake, the microcontroller can get bricked.
This spreadsheet contains options for the low fuse bits CKSEL3,CKSEL2, CKSEL1 and CKSEL0. This will help us to choose which clock source we need to use for our microcontroller. I have made this google sheet from the datasheet of Atmega8, please keep it open along with the tutorial
The link for it is here-
So since i am running the microcontroller with an external crystal, i will use the values CKSEL3-CKSEL0 which correspond to that option. But we see that, the values lie in between the range 1111-1010. To choose the exact value, we need to look up at another table which contains the frequency values which we want for the microcontroller. Here is a table which contains CKOPT value and CKSEL3-1 values according to the frequency.Here is the link- https://docs.google.com/spreadsheets/d/11rt148hgXhwvduZ4aEDTvDKYT3pGxDHP5RUNvuYWNPc/edit?usp=docslist_api
From here i am choosing the programmed CKOPT value(0). Programmed CKOPT value is used for high frequency operations. I am also choosing CKSEL3-1 values as 111.
Now we need options from which we can choose the values of CKSEL0 and SUT1 and SUT0. Here is the link- https://docs.google.com/spreadsheets/d/1028hW05QgAiBQzUzOMjDfJ1VCY8tcOMtgQAsnH5xOWw/edit?usp=docslist_api
If you look up the table, you will find a list of options for start up time and their corresponding bit value. I am choosing crystal oscillator with 65 millisecond start up delay time because i am using a cryatal oscillator here. So according to the table the CKSEL0 value will be 1 , SUT1 value will be 1 , and SUT0 value will be 1.
Since we are using crystal oscillator and start up time corresponding to the crytal oscillator, our CKSEL3-CKSEL0 values become 1111.
This completes our selecting options.
Step 6: Summing Up.
The previous step might look confusing and out of order but this step will give a clear picture of the whole process.
So what do we actually want to do?
We have a microcontroller(here Atmega 8). It runs on the default frequency it was shipped with. We want to run it on 16Mhz external crystal.
So what to do exactly? Only see and change fuse bit values. We should also not forget that 1 means unprogrammed and 0 means programmed.
Now, the chip is sitting with its default fuse byte configuration.
First of all we need to decide, how to run the microcontroller? For simplicity, lets take that we only have three options- external crystal, external resonator or internal oscillator.
We found out that crystal oscillator is a reliable time keeping sourceand we dont mind spending a little for two 22pf capacitors. Our choice is now clear, we want to run the avr chip with an external crystal.
But where to get the options for making the choice of external crystal oscillator?
The options are available at CKSEL3 to CKSEL0 in the Low fuse byte.
We looked up the table provided in the microcontroller's datasheet and found out that there is an option called cermaic resonator or crytal oscillator. We certainly want this, so we note down the bit values of CKSEL3-CKSEL0 associated with it.
Hmm, but there is a range of values for that, 1111-1010. Which one to specifically take? And how to specify the frequency of the crystal oscillator? Obviously there are many frequencies available for crystals, we want to run it only on 16Mhz.
For this, we look up at another table, containing the frequency and the recommended range of capacitors to be used with them.
In this table, we find that 16Mhz is greater that 1 Mhz so we choose that option. The bit value that was associated with CKOPT for our choice is 0 and along with that, we chose 111 for the values of CKSEL3-CKSEL1.
Now we are certain that we are running the avr chip with an external crytal of 16Mhz.
We just read an instructable about fuse bits and it talked of some start up time stuff which the crytal needs to warm up and start giving relaible signals.
How do we find it ?
We find it again in a table provided in the same instructable. Now this table contains CKSEL0 value and SUT1 and SUT0 value. We choose the option of start up time of 65 milliseconds and thus our corresponding bit values are CKSEL0 -1, SUT1- 1, SUT0- 1.
We thus successfully completed choosing the set of Low fuse byte.
Initially the high fuse byte setting was-
6)WDTON - 1
Now we have to change them to-
That is 11001001 in binary or C9 in hexadecimal. We are only changing the CKOPT from 1 to 0, leaving all others untouched.
Now for the low fuse byte, intially it was-
0) CKSEL0 -1
We are changing it to-
0) CKSEL0 -1
That is 11111111 in binary or FF in hexadecimal.
Now since we are done doing evrything, we just need to burn these new settings in the microcontroller.
Using avrdude syntax, it should be-
avrdude -c usbasp -p m8 -U lfuse:w:0b11111111:m -U hfuse:w:0b11001001:m
But it is better to write this in hexadecimal, like-
avrdude -c usbasp -p m8 -U lfuse:w:0xff:m -U hfuse:w:0xC9:m
The default values for Atmega8 internal 1Mhz oscillator was-
avrdude -p atmega8 -c usbasp -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m
Finally, the total procedure ends here. Though this does not completely explain about fuses and how to program them, this definately gives a rough idea for beginners on what are fuses and how they are to be handled.
Happy DIY-ing :)