8. ADC Assembly Code Example
8.1 Full Code
Here is an example of AVR Assembly code to read the ADC from the ADC0 pin using the internal 2.56V reference and a CLK/128 prescaler:
#define __SFR_OFFSET 0x00
#include "avr/io.h"
;------------------------
.global main
main:
LDI R20, 0xFF
OUT DDRD, R20 ; Set Port D as output (ADC result low byte)
OUT DDRB, R20 ; Set Port B as output (ADC result high byte)
SBI DDRC, 0 ; Set pin PC0 as input for ADC0
;-- ADC Initialization --
LDI R20, 0xC0 ; REFS1:REFS0 = 11 → Internal 2.56V
; ADLAR = 0 → Right-justified
; MUX4:MUX0 = 00000 → ADC0
STS ADMUX, R20
LDI R20, 0x87 ; ADEN = 1 → Enable ADC
; ADPS2:ADPS0 = 111 → Prescaler CLK/128
STS ADCSRA, R20
;-- ADC Reading Loop --
read_ADC:
LDI R20, 0xC7 ; Set ADSC = 1 to start conversion
STS ADCSRA, R20
wait_ADC:
LDS R21, ADCSRA ; Read ADCSRA status register
SBRS R21, 4 ; Skip jump if ADIF (bit 4) = 1 (conversion complete)
RJMP wait_ADC ; Wait loop until ADIF is set
;-- Reset ADIF flag --
LDI R17, 0xD7 ; Set ADIF = 1 so the controller can reset the flag
STS ADCSRA, R17
;-- Read conversion result --
LDS R18, ADCL ; Read low-byte from ADCL (MUST read first)
LDS R19, ADCH ; Read high-byte from ADCH
;-- Output result --
OUT PORTD, R18 ; Send low-byte to Port D
OUT PORTB, R19 ; Send high-byte to Port B
RJMP read_ADC ; Repeat reading
8.2 Code Explanation
Initialization Section:
LDI R20, 0xC0
STS ADMUX, R20
0xC0in binary =1100 0000- REFS1=1, REFS0=1 → Internal 2.56V reference voltage
- ADLAR=0 → Right-justified output
- MUX4:MUX0 = 00000 → Reading pin ADC0 (A0)
- This part runs only once during initialization.
LDI R20, 0x87
STS ADCSRA, R20
0x87in binary =1000 0111- ADEN=1 → ADC is enabled
- ADPS2:ADPS0 = 111 → Prescaler CLK/128 (125 kHz at 16 MHz)
Reading Section (Loop):
LDI R20, 0xC7
STS ADCSRA, R20
0xC7in binary =1100 0111- ADEN=1, ADSC=1 → Start one conversion cycle
- ADPS remains the same (CLK/128)
wait_ADC:
LDS R21, ADCSRA
SBRS R21, 4
RJMP wait_ADC
- Polling loop: continuously reads ADCSRA and checks bit 4 (ADIF)
SBRS= Skip if Bit in Register Set → if ADIF=1 (conversion complete), skip RJMP- As long as ADIF=0 (conversion not complete), continue looping
LDI R17, 0xD7
STS ADCSRA, R17
- Resets the ADIF flag by writing a 1 to the ADIF bit
- This is necessary so the next conversion can be detected
LDS R18, ADCL
LDS R19, ADCH
OUT PORTD, R18
OUT PORTB, R19
- Read ADCL first (mandatory), then ADCH
- Send the results to Port D (low-byte) and Port B (high-byte)
- Since it is right-justified: ADCH only contains 2 bits (bits 9 and 8)
No comments to display
No comments to display