Avr Notes
Avr Notes
Questions
An interrupt vector is the memory address of an interrupt handler. The interrupt vector for each interrupt
provided by the AVR microcontrollers can be found in its respective datasheet. The General Interrupt Control
Register (GICR) controls the placement of the Interrupt Vector table.
4. Describe any four addressing modes of AVR microcontroller with suitable example.(4)
Ans: The addressing modes used of AVR Microcontroller as follows: (For more examples w.r.t to each mode please refer
the Mazidi’s book for AVR very detailed explaination is there. And for digram explaining the modes one may refer the
AVR instruction set maual)
Register Direct, Single Register Rd
I/O Direct
Data Direct
Data Indirect
7. Write a .C. program to flash 55H and AAH alternately. Eight LED.s are connected to PORTD of AVR microcontroller.(4)
Ans:
#include <avr/io.h>
#include <util/delay.h>
int main()
{
DDRD = 0xFF; // Configure port D as output
while(1)
{
PORTC = 0x55; // Turn ON LEDs alternately
_delay_ms(250); // Wait 250ms
PORTC = 0xAA; // Turn OFF LEDs
_delay_ms(250); // Wail 250ms
}
return 0;
}
8. Explain with neat diagram ADC module and associated registers ofAVR. (8)
Ans: (For more useful data and related information please go through http://www.avrbeginners.net/)
The Analog to Digital Converter (ADC) is used to convert an analog voltage (a voltage that vary
continuously within a known range) to a 10-bit digital value. For instance, it can be used to log the output of a
sensor (temperature, pressure, etc) at regular intervals, or to take some action in function of the measured
variable value. There are several types of ADCs. The one used by AVR is of the "succesive approximation
ADC" kind. The following is a simplified scheme of the ADC.
At the input of the ADC itself is an analog multiplexer, which is used to select between eight analog
inputs. That means that you can convert up to eight signals (not at the same time of course). At the end of the
conversion, the correponding value is transferred to the registers ADCH and ADCL. As the AVR's registers are
8-bit wide, the 10-bit value can only be held in two registers.
The analog voltage at the input of the ADC must be greater than 0V, and smaller than the ADC's
reference voltage AREF. The reference voltage is an external voltage you must supply at the Aref pin of the
chip. The value the voltage at the input is converted to can be calculated with the following formula:
ADC conversion value = round( (vin/vref)*1023)
Since it is a 10-bit ADC, you have 1024(1024=2^10) possible output values (from 0 to 1023). So, if vin is equal
to 0V, the result of the conversion will be 0, if vin is equal to vref, it will be 1023, and if vin is equal to vref/2 it
will be 512. As you can see, since you are converting a continuous variable (with infinite possible values) to a
variable with a finite number of possible values (elegantly called a "discrete variable"), the ADC conversion
produces an error, known as "quantization error".
Modes of Operation:
The ADC has two fundamental operation modes: Single Conversion and Free Running. In Single
Conversion mode, you have to initiate each conversion. When it is done, the result is placed in the ADC Data
register pair and no new conversion is started. In Free Runing mode, you start the conversion only once, and
then, the ADC automatically will start the following conversion as soon as the previous one is finished.
The analog to digital conversion is not instantaneous, it takes some time. This time depends on the clock signal
used by the ADC. The conversion time is proportional to the frequency of the ADC clock signal, which must be
between 50kHz and 200kHz.
If you can live with less than 10-bit resolution, you can reduce the conversion time by increasing the
ADC clock frequency. The ADC module contains a prescaler, which divides the system clock to an acceptable
ADC clock frequency. You configure the division factor of the prescaler using the ADPS bits (see below for the
details).
To know the time that a conversion takes, just need to divide the number of ADC clock cycles needed
for conversion by the frequency of the ADC clock. Normaly, a conversion takes 13 ADC clock cycles. The first
conversion after the ADC is switched on (by setting the ADEN bit) takes 25 ADC clock cycles. This first
conversion is called an "Extended Conversion". For instance, if you are using a 200kHz ADC clock signal, a
normal conversion will take 65 microsenconds (13/200e3=65e-6), and an extended conversion will take 125
microseconds (25/200e3=125e-6).
ADMUX
Bit Bit Bit Bit Bit Bit 2 Bit 1 Bit 0
7 6 5 4 3
--- --- --- --- --- MUX2 MUX1 MUX0
This register is used to select which of the 8 channel (between ADC0 to ADC7) will be the input to the ADC.
Since there are 8 possible inputs, only the 3 least significant bits of this register are used. The following table
describe the setting of ADMUX.
MUX2 MUX1 MUX0 Selected
Input
0 0 0 ADC0
0 0 1 ADC1
0 1 0 ADC2
0 1 1 ADC3
1 0 0 ADC4
1 0 1 ADC5
1 1 0 ADC6
1 1 1 ADC7
If these bits are changed during a conversion, the change will have no effect until this conversion is
complete. This is a problem when multiple channels are scanned:
The ISR always changes the ADMUX value to the next channel (or some other value that can be
reconstructed by the next ISR) the value in the ADC data register pair is always the conversion result from the
last ADMUX change. When the ISR changes ADMUX from 2 to 3, the value in the data registers is from
channel 2.
ADCSR
These registers hold the result of the last ADC conversion. ADCH holds the two most significant bits, and
ADCL holds the remaining bits.
When ADCL is read, the ADC Data Register is not updated until ADCH is read. Consequently,it is essential
that both registers are read and that ADCL is read before ADCH.
The ATmega series of AVRs have a more complex ADC. They are similar to the ADC explained here, but have
some additional features like (see the datasheet for the details) :
7 Differential Input Channels
2 Differential Input Channels with Optional Gain of 10x and 200x(1)
Optional Left adjustment for ADC Result Readout
Selectable 2.56V ADC Reference Voltage
ADC Start Conversion by Auto Triggering on Interrupt Sources
9. Write a note on Timers of AVR Microcontrollers.
Ans: The AVR has different Timer types. Some AVRs have special timers which support many more modes.
The timers basically only count clock cycles. The timer clock can be equal to the system clock (from the crystal
or whatever clocking option is used) or it can be slowed down by the prescaler first. When using the prescaler
you can achieve greater timer values, while precision goes down.
The prescaler can be set to 8, 64, 256 or 1024 compared to the system clock. An AVR at 8 MHz and a
timer prescaler can count (when using a 16-bit timer) (0xFFFF + 1) * 1024 clock cycles = 67108864 clock
cycles which is 8.388608 seconds. As the prescaler increments the timer every 1024 clock cycles, the resolution
is 1024 clock cycles as well: 1024 clock cycles = 0.000128 seconds compared to 0.125µs resolution and a range
of 0.008192 seconds without prescaler. It's also possible to use an external pin for the timer clock or stop the
timer via the prescaler.
The timers are realized as up-counters. Here's a diagram of the basic timer hardware. Don't panic, I'll
explain the registers below
The 8-bit Timer:
The 8-bit timer is pretty simple: The timer clock (from System Clock, prescaled System Clock or
External Pin T0) counts up the Timer/Counter Register (TCNT0). When it rolls over (0xFF -> 0x00) the
Overflow Flag is set and the Timer/Counter 1 Overflow Interrupt Flag is set. If the corresponding bit in TIMSK
(Timer Interrupt Mask Register) is set (in this case the bit is named "TOIE0") and global Interrupts are enabled,
the micro will jump to the corresponding interrupt vector (in the 2313 this is vector number 7).
The 16-bit Timer
is a little more complex, as it has more modes of operation:
Register Overview:
Write:
When writing the high byte (e.g. TCNT1H), the data is placed in the TEMP register. When the low byte is
written, the data is transferred to the actual registers simultaneously. So the high byte must be written first to
perform a true 16-bit write.
Read:
When reading the low byte, the high byte is read from TCNT1 simultaneously and can be read afterwards. So
when reading, access the low byte first for a true 16-bit read.
TCNT
Most important is the Timer/Counter Register (TCNT1) itself. This is what all timer modes base on. It counts
System Clock ticks, prescaled system clock or from the external pin.
TCCR
The Timer/Counter Control register is used to set the timer mode, prescaler and other options.
TCCR1A:
Bit 7 Bit 0
COM1A1 COM1A0 --- --- --- --- PWM11 PWM10
OCR1
The Output Compare register can be used to generate an Interrupt after the number of clock ticks written to it. It
is permanently compared to TCNT1. When both match, the compare match interrupt is triggered. If the time
between interrupts is supposed to be equal every time, the CTC bit has to be set (TCCR1B). It is a 16-bit
register (see note at the beginning of the register section).
ICR1
The Input Capture register can be used to measure the time between pulses on the external ICP pin (Input
Capture Pin). How this pin is connected to ICR is set with the ICNC and ICES bits in TCCR1A. When the edge
selected is detected on the ICP, the contents of TCNT1 are transferred to the ICR and an interrupt is triggered.
TIMSK and TIFR
The Timer Interrupt Mask Register (TIMSK) and Timer Interrupt Flag (TIFR) Register are used to control
which interrupts are "valid" by setting their bits in TIMSK and to determine which interrupts are currently
pending (TIFR).
Bit 7 Bit 0
TOIE1 OCIE1A --- --- TICIE1 --- TOIE0 ---
TOIE1: Timer Overflow Interrupt Enable (Timer 1); If this bit is set and if global interrupts are enabled, the
micro will jump to the Timer Overflow 1 interrupt vector upon Timer 1 Overflow.
OCIE1A: Output Compare Interrupt Enable 1 A; If set and if global Interrupts are enabled, the micro will jump
to the Output Compare A Interrupt vetor upon compare match.
TICIE1: Timer 1 Input Capture Interrupt Enable; If set and if global Interrupts are enabled, the micro will jump
to the Input Capture Interrupt vector upon an Input Capture event.
TOIE0: Timer Overflow Interrupt Enable (Timer 0); Same as TOIE1, but for the 8-bit Timer 0.
TIFR is not really necessary for controlling and using the timers. It holds the Timer Interrupt Flags
corresponding to their enable bits in TIMSK. If an Interrupt is not enabled your code can check TIFR to
deternime whether an interrupt has occured and clear the interrupt flags. Clearing the interrupt flags is usually
done by writing a logical 1 to them (see datasheet).
Timer Modes
Normal Mode:
In normal mode, TCNT1 counts up and triggers the Timer/Counter 1 Overflow interrupt when it rolls over from
0xFFFF to 0x0000. Quite often, beginners assume that they can just load the desired number of clock ticks into
TCNT1 and wait for the interrupt (that's what I did...). This would be true if the timer counted downwards, but
as it counts upwards, you have to load 0x0000 - (timer value) into TCNT1. Assuming a system clock of 8 MHz
and a desired timer of 1 second, you need 8 Million System clock cycles. As this is too big for the 16-bit range
of the timer, set the prescaler to 1024 (256 is possible as well).
8,000,000/1024 = 7812.5 ~ 7813
0x0000 - 7813 = 57723 <- Value for TCNT1 which will result in an overflow after 1 second (1.000064 seconds
as we rounded up before)
So we now know the value we have to write to the TCNT1 register. So? What else? This is not enough to
trigger the interrupt after one second. We also have to enable the corresponding interrupt and the global
interrupt enable bit. Here's a flow chart of what happens:
You see that it's actually pretty simple. I left out the low level stuff such as Interrupt validation (enabled/global
enable), as you should understand that by now. The contents of TCNT1 are transferred to ICR1 when the
selected edge occurs on the Input Capture Pin and an ISR can be called in order to clear TCNT1 or set it to a
specific value. The ISR can also change the egde which is used to generate the next interrupt.
You can measure the length of a pulse if you change the edge select bit from within the ISR. This can be done
the following way:
Set the ICES (Input Capture Edge Select) bit to 1 (detect rising edge)
When the ISR occurs, set TCNT1 to zero and set ICES to 1 to detect negative egde
When the next ISR is called, the pin changed from high to low. The ICR1 now contains the number of
(prescaled) cycles the pin was high. If the ISR again sets the edge to be detected to rising (ICES=1), the low
pulse time is measured. Now we have the high time AND the low time: We can calculate the total cycle time
and the duty cycle.
It's also possible to connect the Analog Comparator to the input capture trigger line. That means that you can
use the Analog Comparator output to measure analog signal frequencys or other data sources which need an
analog comparator for timing analysis.
PWM Mode
The Pulse Width Modulator (PWM) Mode of the 16-bit timer is the most complex one of the timer modes
available. That's why it's down here.
The PWM can be set up to have a resolution of either 8, 9 or 10 bits. The resolution has a direct effect on the
PWM frequency (The time between two PWM cycles) and is selected via the PWM11 and PWM10 bits in
TCCR1A. Here's a table showing how the resolution select bits act. Right now the TOP value might disturb you
but you'll see what it's there for. The PWM frequency show the PWM frequency in relation to the timer clock
(which can be prescaled) and NOT the system clock.
PWM11 PWM10 Resolution TOP- PWM
value Frequency
0 0 PWM function disabled
0 1 8 bits $00FF fclock/510
1 0 9 bits $01FF fclock/1022
1 1 10 bits $03FF fclock/2046
To understand the next possible PWM settings, I should explain how the PWM mode works. The PWM is an
enhanced Output Compare Mode. In this mode, the timer can also count down, as opposed to the other modes
which only use an up-counting timer. In PWM mode, the timer counts up until it reaches the TOP value (which
is also the resolution of the timer and has effect on the frequency).
When the TCNT1 contents are equal to the OCR1 value, the corresponding output pin is set or cleared,
depending on the selected PWM mode: You can select a normal and an inverted PWM. This is selected with the
COM1A1 and COM1A0 bits (TCCR1A register). The possible settings are:
Non-inverted PWM means that the Output Compare Pin is CLEARED when the timer is up-counting and
reaches the OCR1 value. When the timer reaches the TOP value, it switches to down-counting and the Output
Compare Pin is SET when the timer value matches the OCR1 value.
Inverted PWM is, of course, the opposite: The Output Compare Pin is set upon an up-counting match and
cleared when the down-couting timer matches the OCR1 value. Here are two diagrams showing what this looks
like:
The reason why you can select between inverting and non-inverting pwm is that some external hardware might
need an active-low pwm signal. Having the option to invert the PWM signal in hardware saves code space and
processing time.
The PWM is also glitch-free. A glitch can occur when the OCR1 value is changed: Imagine the PWM counting
down to 0. After the pin was set, the OCR1 value is changed to some other value. The next pulse has an
undefined length because only the second half of the pulse had the specified new length. That's why the PWM
automatically writes the new value of OCR1 upon reaching the TOP value and therefore prevents glitches.
Typical applications for the PWM are motor speed controlling, driving LEDs at variable brightness and so on.