ATmega32 ADC for Light and Temperature Sensors

block diagram

This tutorial shows how to implement the Analogue to Digital Converter (ADC) function on ATMega32 using C code. It consists of code examples, and the meaning of some nomenclature such as sampling rate, and resolution. However before we get to the code, let us start from the beginning. The ATMega32 has a built-in 10-bit ADC. The input to this ADC has a multiplexer to provide eight single-ended channels, where each channel can have a dedicated sensor such as an LDR or a Thermistor to provide an input voltage. These channels share the GPIO pins 33 to 40 on Port A. The output from the multiplexer feeds the non-inverting input of an operational amplifier with programmable gain. The gain is available in the following steps, 0 dB (1×), 20 dB (10×), and 46 dB (200×).

block diagram

There is also an option to have three differential inputs by way of ADC5, ADC6, and ADC7, which feeds a second multiplexer connecting to the inverting input side of the op-amp.

From a hardware consideration, the AVCC pin provides voltage to the ADC circuitry and Port A also. This pin requires connection to the Vcc voltage supply, even when the ADC is not used. However when using the ADC, you should also include a filter capacitor as the ADC requires an extremely clean power supply.

The ADC also has a dedicated clock circuit, which allows the programmer to shut-off all the other clocks to reduce noise and therefore increase the precision of the ADC.

ADMUX Register

7 6 5 4 3 2 1
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
REFS1 REFS0 Methods for selecting Voltage Reference
AREF, Internal Vref turned OFF
1 AVCC with external capacitor at AREF pin
1 Reserved
1 1 Internal 2.56 V Voltage Reference with external capacitor at AREF pin

The ADC requires a reference voltage to determine the conversion range. The analogue signal for sampling must be between ground and Vref for capture.

For most applications, Vcc is sufficient by setting bit REFS0 to binary 1. Vcc is prone to noise so as a result an external decoupling capacitor helps filter this noise.

ADMUX |= _BV (REFS0);

Analog Channel and Gain Selection Bits

In the ADMUX register, the first four “MUX bits” organise as follows. The first seven numbers select single-ended input configuration. From eight onwards you can select a combination of differential inputs with different gain factors. The gain factor is available only for differential inputs.

MUX
4,3,2,1,0
Single Ended +Differential
Input
-Differential
Input
Gain factor
00000 ADC0 NOT
AVAILABLE
00001 ADC1
00010 ADC2
00011 ADC3
00100 ADC4
00101 ADC5
00110 ADC6
00111 ADC7
01000 N/A ADC0 ADC0 10×
01001 ADC1 ADC0
01010 ADC0 ADC0 200×
01011 ADC1 ADC0
01100 ADC2 ADC2 10×
01101 ADC3 ADC2
01110 ADC2 ADC2 200×
01111 ADC3 ADC2
10000 ADC0 ADC1
10001 ADC1 ADC1
10010 ADC2 ADC1
10011 ADC3 ADC1
10100 ADC4 ADC1
10101 ADC5 ADC1
10110 ADC6 ADC1
10111 ADC7 ADC1
11000 ADC0 ADC2
11001 ADC1 ADC2
11010 ADC2 ADC2
11011 ADC3 ADC2
11100 ADC4 ADC2
11101 ADC5 ADC2
11110 1.22V (VBG) N/A
11111 0V (GND)

In a simple case, we can use a single-ended input. Any port from ADC0 to ADC7 will work. The ADC port can be any number from 0 to 7 and passed through the following functions.

  1. ReadADC(uint8_t ADCport);
  2. ADCport=ADCport & 0b00000111;
  3. ADMUX|=ADCport;

ADCSRA – Control and Status Register

7 6 5 4 3 2 1
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0

ADCSRA |= _BV (ADEN);

Bit 7 – ADEN: Set this to binary 1 to enable the microcontroller ADC circuits, whilst binary 0 will switch it OFF.

ADCSRA |= _BV (ADSC);

Bit 6 – ADSC: Setting ADSC bit to binary 1 starts the conversion process. This bit clears automatically when the conversion process completes. Therefore, this bit provides an indication that the conversion has completed.

While (ADCSRA & _BV (ADSC));

This while loop waits for the ADSC bit to become binary 0 again.

ADPS2, ADPS1, ADPS0

These bits determine the division factor between the XTAL frequency and the ADC input clock.

Converting an analogue signal to digital requires a clock frequency for the approximation circuitry. This principle is similar to the strips under a curve in maths class. The more strips the better the approximation of the analogue signal. A frequency between 50 kHz and 200 kHz is typical for maximum resolution.

The prescaler frequency is a fraction of the crystal frequency, usually achieved by using a division factor. The bits ADPS2, ADPS1, ADPS0, determine the division factor.

ADPS2 ADPS1 ADPS0 Division Factor
2
1 2
1 4
1 1 8
1 16
1 1 32
1 1 64
1 1 1 128

16000000 / 128 = 125 kHz

This ATMega32 development board has a 16 MHz crystal; therefore, a division of 128 provides 125 kHz for the prescaler frequency.

ADCSRA |= _BV (ADPS2) | _BV (ADPS1) | _BV (ADPS0);

This value is within the maximum resolution range so we choose a prescaler division factor of 128 by setting bits ADPS2, ADPS1, ADPS0 to binary 1.

ADC Example C Code

This program displays the sampled ADC value on HyperTerminal, so you will need a working UART circuit. Make sure you have a working MAX232 interfacing circuit connected to the UART. Make sure you have tested the UART communications with HyperTerminal using uart.h and uart.c include files as shown in the following section. ATMega32 UART PC Interface – Testing

Leave a Comment

Your email address will not be published. Required fields are marked *