- Usually written as A/D Conversion or ADC.
- Analog — Infinite number of possible values.
- Digital — Finite number of possible values represented by a sequence of zeros and ones.
- A transducer is a device that converts from one form of energy to another.
- A pressure transducer converts pressure into a voltage.
- A temperature transducer converts temperature to a voltage.
- PORTA is the analog input port on the ATmega32.
- The ATmega32 has a built in A/D converter which is attached to PORTA.
- PORTA consists of eight pins (called analog input channels).
- The ADC converts the voltage on an input channel into a digital representation.
- Input channels on the ATmega32 can handle voltages between 0 and 5 volts.
- A signal conditioning circuit can be used to convert an analog signal so that it stays in the range of 0 to 5 volts.
- The resolution of an ADC is the range of input voltage divided by 2n where n is the number of bits in the digital result.
- For the ATmega32, n = 10 and the voltage range is 5 volts, so the resolution is 5v/1024 = 0.00488 volts.
- This means that we cannot tell the difference between voltage variations that are less than 0.00488 volts.
- We can operate the ADC in 8 bit mode where our resolution is now 5v/28 = 19.4 mV.
- We can calculate the digital value produced by the ADC as follows: (Digital Output)10 = (Analog Input)/resolution.
- If we know the result of the ADC, we can determine the voltage on the input as follows: (Analog Input) = (Digital Output)10 * resolution.
- For the ATmega32, we have 10 bits and a range of 0 to 5 volts. Each bit represents a specific contribution to the total voltage measured by the ADC:
- b9 = 5 / 2 = 2.5 V
- b8 = 5 / 4 = 1.25 V
- b7 = 5 / 8 = 0.625 V
- b6 = 5 / 16 = 0.3125 V
- b5 = 5 / 32 = 0.15625 V
- b4 = 5 / 64 = 0.078125 V
- b0 = 5 / 1024 = 0.0048828125 V
I/O Registers Needed
- ADCH — High byte of ADC result.
- ADCL — Low byte of ADC result.
- ADMUX — Analog to Digital Multiplexer.
- Selects which of the eight channels (on PORTA) is being converted.
- REFS1 and REFS0 — Reference Select bits
- Used to select reference voltage for ADC.
- We will use REFS1 = 0 and REFS0 = 1 (use AVCC as the reference voltage).
- Using REFS1 = 0 and REFS0 = 0 selects AREF as the reference voltage.
- For the SunRom board, this is attached to a potentiometer that can adjusted between 0 and 5V.
- This can be useful if you want to get even higher resolution. For example, if AREF is set to 1V, the 10-bit resolution for the ADC is 1/210 = 0.000977 V (5 times better than if AREF were 5V).
- ADLAR — Analog to Digital Left Adjust Register.
- If ADLAR = 0 then two most significant bits of ADC result go in the two least significant bits of ADCH and the eight least significant go in ADCL.
- If ADLAR = 1 then eight most significant bits of ADC result go in ADCH and the two least significant bits are the two most significant bits of ADCL.
- ADLAR = 1 makes it easy to do eight bit conversion because we have the eight most interesting bits stored in one register.
- MUX4 and MUX3 — Gain selection bits
- We will set MUX4 = 0 and MUX3 = 0, single ended analog input channel.
- Single ended means we're just using one channel for ADC.
- There are other modes where you can do things like monitor two channels and ADC the difference in voltage between the two channels.
- MUX4-0 = 10000 would ADC the difference in voltage between PA1 and PA0.
- MUX4-0 = 01001 would ADC 10 times the difference in voltage between PA1 and PA0.
- MUX2-0 — When MUX4-3 = 00, used to select the analog input channel (which pin of PORTA).
- REFS1 and REFS0 — Reference Select bits
- We will typically use 01100xxx for ADMUX where the three least significant bits select which pin on PORTA we wish to convert.
- See ATmega32 Datasheet pp. 212-214 for details.
- ADCSRA — Analog to Digital Control and Status Register A.
- ADEN — Analog to Digital Enable (active high)
- ADSC — Analog to Digital Start Conversion (active high)
- When set, conversion begins.
- When conversion is complete, the bit gets cleared.
- We can poll this bit in order to determine when we can look at ADCH and ADCL.
- ADATE — Analog to Digital Automatic Trigger Enable (active high)
- Does continual conversions on the selected channel.
- Operates in conjunction with the Special Function IO Register (SFIOR).
- ADIF — Analog to Digital Interrupt Flag
- Set to high when ADC is complete.
- This bit is reset one of two ways:
- Manually with:
sbi ADCSRA, ADIF ; clears the AD interrupt flag
- This may seem counter-intuitive since doing an SBI instruction will actually clear the flag.
- Automatically cleared when its interrupt vector is executed (more on this when we discuss interrupts).
- ADIE — Analog to Digital Interrupt Enable
- If enabled, an interrupt occurs when ADIF flag goes high.
- Once the interrupt occurs, the ADIF flag is reset.
- ADPS2-0 — Analog to Digital Prescaler Select bits
- We will just set these all high.
- Used to reduce the clock speed for the ADC (since running at 16MHz is too fast for ADC).
- ADPS2-0 = 111 selects a division factor of 128.
- See ATmega32 Datasheet pp. 214-216 for details.
- SFIOR — Special Function IO Register.
- For ADC, we only care about ADTS2-0 — Auto Trigger Source.
- Only interesting if ADATE is enabled.
- Look-up table determines mode.
|ADTS2||ADTS1||ADTS0||Mode of operation|
|0||1||0||External Interrupt Request 0|
|0||1||1||Timer/Counter0 Compare Match|
|1||0||1||Timer/Counter Compare Match B|
|1||1||1||Timer/Counter1 Capture Event|
- 000 for the three most significant bits puts it into free-running mode which means that it will just continue doing ADC as quickly as it can.
- Other modes can be useful for sampling at specific intervals.
- See ATmega32 Datasheet pp. 216 for details.
- All of these registers are accessed with IN and OUT instructions.
The following function uses the ADC in polling mode (does one conversion and stores the result when the conversion has completed).
; Initialize ADC for single ended conversion on ADC channel 0 (PA0) init_adc0: push r16 ; Set ADC reference voltage, put in 8 bit mode and select channel 0 ldi r16, 0b01100000 ; REFS0 = 1, ADLAR=1 (left adjust result), select ADC0 out ADMUX, r16 ; Enable ADC and divide clock speed by 128 ldi r16, 0b10000111 ; ADEN = 1, Prescale by factor of 128 out ADCSRA, r16 pop r16 ret ; Perform a single ADC ; Assume ADC has been initialized for single ended input on the relevant channel ; with left adjust result set ; Returns result in r24 single_adc: sbi ADCSRA, ADSC ; Start ADC sadcPoll: sbic ADCSRA, ADSC ; Wait until conversion is complete rjmp sadcPoll in r24, ADCH ; Put 8 MSBs of ADC in ret