Lec - 12 Revised by Prof
Lec - 12 Revised by Prof
by
Dr. Han-Way Huang
05/13/2025 1
Basics of Analog-to-Digital Converter
Many embedded systems are required to deal with nonelectric
quantities such as weight, humidity, temperature, pressure,
acceleration, airflow, massflow, speed, and so on.
Nonelectric quantities must be converted to electric voltages
and then to digital values before they can be processed by a
computer.
A transducer is used to convert a nonelectric quantity into an
electric voltage.
The output from a transducer is analog (i.e., continuous over a
range) in nature.
05/13/2025 2
To convert an electric quantity to a digital value, an analog-
to-digital converter (ADC) is required.
A data acquisition system is shown in Figure 8.1.
temperature
pressure Digital
Signal-
Voltage Voltage A/D value
light Transducer conditioning Computer
weight circuit converter
airflow
Such as a (optional)
humidity sensor,
. load cell,
. photocell, or
. thermocouple
. Figure 16.1 The A/D conversion process
.
05/13/2025 3
Signal Conditioning
The output of a transducer may not be in an appropriate
range to be converted by an A/D converter.
In some situations, the output can be amplified to take
advantage of the dynamic range of the ADC by using a
scaling circuit shown in Figure 8.2.
In other situations, the output must be shifted and scaled to
take advantage of the dynamic range of the ADC by using a
circuit as shown in Figure 8.3.
05/13/2025 4
Scaling Circuit
Example 12.1 Find appropriate values for R1 and R2 so that the circuit shown in
Figure 8.2 can scale the voltage from the range 0V~0.2V to 0~3.3V.
Solution:
We can choose 51 kW and 3.3 kW for R2 and R1, respectively to achieve this ratio.
05/13/2025 5
Example 12.2 Find appropriate values for R1 and R2 so that the
circuit shown in Figure 8.2 can scale the voltage from the range 0 V
~ 0.11 V to 0 V ~ 3.3 V.
Solution:
05/13/2025 7
Voltage Translation Circuit
Translate (shift and then scale) a voltage from V1~V2 to
0~VDD.
V1 may be negative
Made of Op Amp inverting and summing circuits
05/13/2025 8
05/13/2025 9
Example 12.3 Choose appropriate resistor values and adjusting voltage V1 so
that the circuit in Figure 8.3c can shift the voltage from the range of - 1.1 V ~ 2.2
V to the range of 0 V ~ 3.3 V.
Solution: Applying equation 8.3:
0 = -1.1 (Rf / R1) – (Rf / R2) V1 ----- (1)
VRH.
For simplicity reason, VRL is often set to GND.
All ADCs are ratiometric; i.e., the voltage VRL is converted to 0 whereas
05/13/2025 14
Conversion Range—(continued)
Regardless of the conversion mode, input voltage on any
channel must stay between GND and AVCC (analog voltage
power supply).
In the single-ended mode, the single channel voltage is
converted to digital value.
In the differential mode, the output of a differential
amplifier (with an optional gain stage) is converted to a digital
value.
05/13/2025 15
05/13/2025 16
Input Sources
Four types of measurement that can be performed
Differential input
Differential input with gain
Single-ended input
Internal input
In devices with two ADCs (e.g., XMEGA128A1U), PORTA pins
can be input to ADCA and PORTB pins can be input to ADCB.
05/13/2025 17
•Differential Input
• When differential input
is enabled, all input pins
can be selected as
positive input, and input
pins 0 to 3 can be
selected as negative
input.
• The ADC must be in
signed mode when
differential input is used.
05/13/2025 18
Differential Input with Gain
All input pins can be selected as positive input, and input pins 4
to 7 can be selected as negative input.
The differential input is first sampled and amplified by the gain
stage before the result is fed into the ADC. Gain can be 1/2x, 1x,
2x, 4x, 8x, 16x, 32x, and 64x.
05/13/2025 19
Single-Ended Measurement in
Signed Mode
05/13/2025 20
Single-Ended Measurement in Unsigned
Mode
05/13/2025 21
AVR ADC Reference Voltage
The AVR devices use a single VREF as the reference voltage for
A/D conversion.
For a 12-bit differential mode operation, the voltage
05/13/2025 22
ADC Transfer Function
RES = (VINP - VINN) × GAIN × (TOP +1) ÷ VREF
VINP and VINN are the positive and negative input
For differential measurements, GAIN is ½ to 64.
For single ended and internal measurement, GAIN is 1
05/13/2025 25
The XMEGA ADC Module—(continued)
Reference voltages: both internal and external reference
voltages are available.
A clock signal (called ADC clock) is needed for the A/D
conversion.
ADC startup time: After enabling the ADC block, the user
must wait for at least 12 up to 24 ADC clock cycles before using
it.
05/13/2025 26
Pipelined Architecture and Virtual Channels of XMEGA ADC
Virtual
Pin inputs Channel 0 Result Register 1
.
. Virtual
Result Register 2
Channel 1
. Pipelined
Gain ADC block
Virtual Result Register 3
Internal inputs
Channel 2
Event
System Result Register 4
Virtual
Channel 3
Figure 13.9 XMEGA ADC overview
05/13/2025 27
Pipelined Architecture of XMEGA ADC
The output of the input multiplexer of XMEGA A series can be
sampled every clock cycle.
Each signal propagates through the pipeline, where 1 bit is
converted. This allows the ADC to sample one signal every
ADC clock cycle even if each signal must propagate through all
stages in the pipeline before result is ready in the result
register.
The propagation time for one single signal through the
pipeline is 7 ADC clock cycles for 12-bit resolution and 5 cycles
for 8-bit resolution.
05/13/2025 28
Pipelined Architecture of XMEGA ADC—(continued)
If gain is used, the propagation time increases by 1 cycle.
Each channel has
a MUX control register (ADCx_CHn_MUXCTRL, x = A or B, n =
0~3),
a channel control register (ADCx_CHn_CTRL),
a channel interrupt control register (ADCx_CHn_INTCTRL),
a channel interrupt flag register (ADCx_CHn_INTFLAGS),
and
a result register pair (ADCx_CHn_RESL and
ADCx_CHn_RESH).
05/13/2025 29
Input Gain Stage
Gain stage enables the measurement of small voltages in
differential mode.
The gain stage is shared by all four channels.
The ADC gain of XMEGA128A1U can be 1, 2, 4, 8, 16, 32,
and 64.
How to set the ADC gain? By programming the channel
control register.
Conversion time for an ADC sample through ADC module
increases by 1 ADC clock cycle for all gain factor in the A
series devices.
05/13/2025 30
Input Sources of XMEGA ADC
Differential input without gain
Differential input with gain
Single-ended input
Internal input
05/13/2025 31
Differential Inputs without Gain
ADC0
ADC1
ADC2
ADC3
ADC4 +
ADC5 ADC
ADC6 -
ADC7
ADC0
ADC1
ADC2
ADC3
Figure 16.18 Differential measurement without gain
05/13/2025 32
Differential Input with Gain
ADC0
ADC1
ADC2
ADC3
ADC4 +
ADC5 1-64 x ADC
ADC6 -
ADC7
ADC4
ADC5
ADC6
ADC7
Figure 16.19 Differential measurement with gain
05/13/2025 33
Single-Ended Input
ADC0
ADC1
ADC2
ADC3 +
ADC4 ADC
ADC5 -
ADC6
ADC7
ADC0
ADC1 DV = VREF ×
ADC2 0.05
ADC3 +
ADC4 ADC
ADC5 VREF -DV -
ADC6 2
ADC7
Figure 16.21 Single-ended measurement in unsigned mode
05/13/2025 34
Internal Inputs
TEMP REF
DAC +
VCC SCALED ADC
BANDGAP REF -
05/13/2025 35
Reference Voltage for ADC
Internal 1.0 V voltage
Internal VCC/1.6 (3.3 V ÷ 1.6 = 2.0625 V)
External reference on PORTA—AREFA (pin 0)
External reference on PORTB—AREFB (pin 0)
AVcc/2—Internal reference of AVCC/2 (XMEGA D only)
05/13/2025 36
Registers In the whole ADC module (A or B)
ADCx_CTRLA Control A (x = A or B)
ADCx_CTRLB Control B
ADCx_REFCTRL Reference voltage control
ADCx_EVCTRL Event control
ADCx_PRESCALER ADC clock prescaler
ADCx_INTFLAGS Interrupt flags
ADCx_TEMP temporary register
ADCx_CAL Calibration value register (two bytes)
ADCx_CHnRES channel n result register (n = 0, 1, 2, or 3, each
result is two bytes)
ADCx_CMP compare register (two bytes)
05/13/2025 37
ADC Channel Registers (x = A or B, n = 0,..,3)
ADCx_CHn_CTRL channel control register
ADCx_CHn_MUXCTRL channel input multiplexer
register
ADCx_CHn_INTCTRL interrupt control register
ADCx_CHn_INTFLAGS interrupt flag register
ADCx_CHnRES result register (two bytes)
ADCx_CHn_SCAN scan register
05/13/2025 38
ADCx_CHn_MUXCTRL
register
7 6 5 4 3 2 1 0
Reset value
- MUXPOS[3:0] - MUXNEG[1:0] = 0x00
R R/W R/W R/W R/W R R/W R/W
MUXPOS[3:0]: MUX selection on positive ADC input
When single-ended mode or differential mode is selected, the analog
input selection is shown in Table 13.3. When internal source is selected, the
selection is shown in Table 13.4.
Table 13.3 External pins selected as Positive ADC Table 13.4 Internal source selected as Positive ADC
input input
MUXPOS[3:0] Group configuration Analog input Group
MUXPOS[2:0] Analog input
configuration
0000 PIN0 ADC0 pin
0001 PIN1 ADC1 pin 000 TEMP Temperature ref.
0010 PIN2 ADC2 pin 001 BANDGAP Bandgap voltage
0011 PIN3 ADC3 pin 010 SCALEDVCC VCC/10
0100 PIN4 ADC4 pin 011 DAC DAC output
0101 PIN5 ADC5 pin 100~111 reserved
0110 PIN6 ADC6 pin
0111 PIN7 ADC7 pin
05/13/2025 39
ADCx_CHn_MUXCTRL
register
7 6 5 4 3 2 1 0
Reset value
- MUXPOS[3:0] - MUXNEG[1:0] = 0x00
R R/W R/W R/W R/W R R/W R/W
05/13/2025 40
ADCx_CHn_CT 7 6 5 4 3 2 1 0
START - - GAIN[2:0] INPUTMODE[1:0] Reset value
RL R/W R R R/W R/W R/W R/W R/W
= 0x00
05/13/2025 41
Table 16.7 Channel input modes, CONMODE =0 (unsigned mode)
Group
INPUTMODE[1:0] Description CONMODE is a bit in
Configuration
ADCx_CTRLB register.
00 INTERNAL Internal positive input signal 0: unsigned mode
01 SINGLEENDED Single-ended positive input signal 1: signed mode
10 Reserved
11 Reserved
05/13/2025 42
ADCx_REFCTRL
Register
7 6 5 4 3 2 1 0
- - REFSEL[1:0] - - BANDGAP TEMPREF Reset value
= 0x00
R R R/W R/W R R R/W R/W
REFSEL[1:0]: ADC reference selection
REFSEL[1:0] Group configuration Description AREF pin is PA0
00 INT1V Internal 1.00 V pin
01 INTVCC Internal VCC/1.6
10 (1)
AREFA External reference from AREF pin on Port A
BREF pin is PB0
11 (2)
AREFB External reference from AREF pin on Port B pin
ADCA0 ~ ADCA7
BANDGAP:
0: disable bandgap input
1: enable bandgap to prepare for ADC measurement correspond to
TEMPREF: temperature reference enable PA0~PA7 pins
0: disable temperature reference
1: enable temperature reference
ADCB0 ~ ADCB7
Note. 1. Only available if AREF exists on Port A inputs
2. Only available if AREF exists on Port B correspond to
Figure 13.18 ADC reference control register (ADCx.REFCTRL, x = A or B) PB0~PB7 pins
VREFmax = VCC –
0.6V
05/13/2025 43
Conversion Result of XMEGA ADC
05/13/2025 44
ADCx_CTRLB
register
7 6 5 4 3 2 1 0
- - - CONVMODE FREERUN RESOLUTION[1:0] - Reset value
=0x00
R R R R/W R/W R/W R/W R/W R
CONVMODE: ADC conversion mode
0 =unsigned mode
1=signed mode
FREERUN: ADC free running mode
0 =single conversion mode
1=free running mode
RESOLUTION[1:0]: The bits define whether ADC completes the conversion at 12- or
8-bit result.
RESOLUTION[1:0] Group configuration Description
00 12BIT 12-bit result, right justified
01 Reserved
10 8BIT 8-bit result, right justified
11 LEFT12BIT 12-bit result, left justified
Figure 16.25 ADC control register B (ADCx.CTRLB, x =A or B)
05/13/2025 45
Compare Function
ADC has a built in 12-bit compare register (ADCx_CMPH:
ADCx_CMPL).
ADC result can be programmed to compare to this register to
generate interrupts.
All four ADC channels share the same compare register.
Use the name ADCx_CMP & ADCx_CMP+1 (x = A or B) to
access them.
05/13/2025 46
XMEGA ADC Interrupts
Conversion complete
Compare result below threshold
Compare result above threshold
7 6 5 4 3 2 1 0
- - - - CH[3:0]IF
R R R R R/W R/W R/W R/W
CH[3:0]IF: Interrupt flags
These flags are set when the ADC conversion is complete for the corresponding ADC
channel. If an ADC channel is configured for compare mode, the corresponding flag
will be set if the compare condition is met. These flags will be cleared when their
interrupt service routine have been entered. They also can be cleared by writing 1
to them.
Figure 16.26 ADC interrupt flag register (ADCx.INTFLAGS, x = A or B)
05/13/2025 47
ADC Channel Interrupt Control
(ADCx_CHn_INTCTRL)
7 6 5 4 3 2 1 0
- - - - INTMODE[1:0] INTLVL[1:0] Reset value
= 0x00
R R R R R/W R/W R/W R/W
INTMODE[1:0]: ADC interrupt mode
INTMODE[1:0] Group configuration Interrupt mode
00 COMPLETE Conversion complete
01 BELOW Compare result below threshold
10 Reserved
11 ABOVE Compare result above threshold
05/13/2025 48
Starting an XMEGA ADC Conversion
A/D conversion can be started by setting the START bit
contained in the CTRLA register or the event input.
To use event to start an A/D conversion, the user is required to
program the ADC event control register (ADCx_EVCTRL).
05/13/2025 49
ADCx_CTRLA Register (part
1)
7 6 5 4 3 2 1 0
DMASEL[1:0] CH[3:0]START FLUSH ENABLE Reset value
= 0x00
R/W R/W R/W R/W R/W R/W R/W R/W
DMASEL[1:0]: DMA request selection
In addition to giving DMA transfer request for each ADC channel, the ADC can be set
up to give a combined request for all channels. The combined request is decided
according to the DMASEL bits.
DMASEL[1:0] Group configuration Description
00 OFF No combined DMA request
01 CH01 ADC channel 0 or 1
10 CH012 ADC channel 0 or 1 or 2
11 CH0123 ADC channel 0 or 1 or 2 or 3
05/13/2025 50
ADCx_CTRLA Register (part 2)
7 6 5 4 3 2 1 0
DMASEL[1:0] CH[3:0]START FLUSH ENABLE Reset value
= 0x00
R/W R/W R/W R/W R/W R/W R/W R/W
05/13/2025 51
XMEGA ADC Clock and Conversion Timing
ADC clock is derived by dividing the peripheral clock by a
prescaler.
The prescaler is selected by programming the ADC clock
prescaler register (ADCx_PRESCALER).
The ADC conversion time is given by
Conversion time (ADC cycles) = (1 + RES/2 + Gain) --
(Gain = 0 or 1)
05/13/2025 52
ADCx_PRESCALER
register
7 6 5 4 3 2 1 0
- - - - - PRESCALER[2:0] Reset value
= 0x00
R R R R R R/W R/W R/W
PRESCALER[2:0]: ADC prescaler configuration
PRESCALER[2:0] Group configuration Peripheral clock divide factor
000 DIV4 4
001 DIV8 8
010 DIV16 16
011 DIV32 32
100 DIV64 64
101 DIV128 128
110 DIV256 256
111 DIV512 512
Figure 16.31 ADC clock prescaler register (ADCx.PRESCALER, x = A or B)
05/13/2025 53
XMEGA ADC Free-Running Mode
ADC module can be placed in free-running mode.
In free-running mode, several channels are repeatedly
converted in sequence.
The channel sweep selection (SWEEP) in the event
control register in Figure 13.24 selects the channels to
be included in the free-running mode.
05/13/2025 54
ADCx_EVCTRL
Register 7 6 5 4 3 2 1 0
SWEEP[1:0] EVSEL[2:0] EVACT[2:0] Reset value
= 0x00
R/W R/W R/W R/W R/W R/W R/W R/W
SWEEP[1:0]: ADC channel sweep
Th ese bits control which ADC channels are included in a channel sweep triggered by
the event system or in free running mode.
SWEEP[1:0] Group configuration Description
00 0 Only ADC channel 0
01 01 ADC channel 0 and 1
10 012 ADC channel 0, 1, and 2
11 0123 ADC channel 0, 1, 2, and 3
EVSEL[2:0]: ADC channel start single conversion
Th ese bits defi ne which event channel should trigger which ADC channel. Each setting
defines a group of event channels, where the event channels with the lowest number
will trigger ADC channel 0 and the next event channel will trigger ADC channel 1 and
so on. Th e event channel selection is defined in Table 13.8.
EVACT[2:0]: ADC event mo de
Th ese bits defi ne how many of the selected event channel that are in use, and also
some special event modes as defined in Table 13.9.
Figure 13.24 ADC event control register (ADCx.EVCTRL, x = A or B)
05/13/2025 55
Table 13.8 ADC event line select
EVSEL[2:0] Group configuration Selected event lines
000 0123 Event channel 0, 1, 2, 3, as selected inputs
001 1234 Event channel 1, 2, 3, 4 as selected inputs
010 2345 Event channel 2, 3, 4, 5 as selected inputs
011 3456 Event channel 3, 4, 5, 6, as selected inputs
100 4567 Event channel 4, 5, 6, 7 as selected inputs
101 567 Event channel 5, 6, 7 as selected inputs
110 67 Event channel 6, 7 as selected inputs
111 7 Event channel 7 as selected input
05/13/2025 56
Table 13.9 ADC event mode select
EVACT[2:0] Group configuration Event input operation mode
000 NONE No event inputs
001 CH0 Event channel with the lowest number, defined by EVSEL trigger
conversion on channel 0.
010 CH01 Event channel with the two lowest numbers, defined by EVSEL trigger
conversion on channel 0 and 1 respectively.
011 CH012 Event channel with the three lowest numbers, defined by EVSEL
trigger conversion on channel 0, 1, and 2 respectively.
100 CH0123 Event channel defined by EVSEL trigger conversion on channel 0, 1, 2,
and 3, respectively.
101 SWEEP One sweep of all active ADC channels defined by SWEEP on incoming
event channel with the lowest number, defined by EVSEL.
110 SYNCSWEEP One sweep of all active ADC channels defined by SWEEP on incoming
event channel with the lowest number, defined by EVSEL. In addition,
the conversion will be synchronized on event to ensure a very
accurate timing for the conversion.
111 Reserved
05/13/2025 57
Example 12.6 Write a subroutine to configure ADCA with the
following setting:
Select PA1 pin as channel 0 input
Select unsigned mode, disable free-running, select 12-bit
resolution, result right-justified.
Use AREFA pin input as channel 0 reference voltage
Enable ADCA
Start A/D conversion using software
Set the ADC clock prescaler to 32
Select single-channel mode
Set ADCA channel 0 to interrupt high priority but not enable it
05/13/2025 58
initADCA_CH0:
ldi r16, 0x01
sts ADCA_CTRLA, r16 ; enable ADCA module
ldi r16, 24 ; wait until ADCA is ready (ADC startup time)
call delayby1us ; “
ldi r16, 0x10 ; select signed, single conversion mode,
sts ADCA_CTRLB, r16 ; 12-bit resolution, result right aligned
ldi r16, 0x22 ; select AREFA as reference, enable BANDGAP
sts ADCA_REFCTRL, r16 ; “
clr r16
sts ADCA_EVCTRL, r16 ; no event input
ldi r16, 0x03
sts ADCA_PRESCALER, r16 ; set ADC clock to 1 MHz (generic clock
divided by 32)
ldi r16,0x0F ; clear all ADC IF flags
sts ADCA_INTFLAGS, r16
ldi r16, 0x08
sts ADCA_CH0_MUXCTRL, r16 ; select ADC1 pin as positive input of
channel 0
05/13/202 59
5
ldi r16, 0x01
sts ADCA_CH0_CTRL, r16 ; select single-ended input (signed)
mode
ldi r16, 0x03 ; select ADC completion interrupt &
sts ADCA_CH0_INTCTRL, r16 ; set ADCA channel 0 interrupt to high
level
ret
delayby1us:
uslp1: ldi r20, 4 ; 1 CPU clock cycle
uslpi: push r0 ; 2 CPU clock cycles
pop r0 ; 2 CPU clock cycles
dec r20 ; 1 CPU clock cycle
brne uslpi ; 2 (1) CPU clock cycle
dec r16 ; 1 CPU clock cycle
brne uslp1 ; 2 (1) clock cycles
ret ; 2 CPU clock cycles
05/13/2025 60
Example 12.7 Write a subroutine to configure the ADCB channel 0 to operate in
the following manner:
Select PB1 pin as channel 0 input
Use the AREFB pin (PB0 pin) as reference voltage
Select signed mode, disable free-running, select 12-bit resolution, result
right-justified.
Enable ADCB
Start ADC conversion every 250 ms (triggered by timer overflow)
Set the ADC clock prescaler to 32
Select single-ended mode
Select ADCB channel 0 to interrupt high priority but not enable it
Solution:
05/13/2025 61
initADCB_CH0:
ldi r16, 0x01 ; enable ADCB module
sts ADCB_CTRLA, r16
ldi r16, 24
call delayby1us ; wait for 24 us until ADCA is ready
ldi r16, 0x10
sts ADCB_CTRLB, r16 ; single conversion mode, 12-bit resolution
ldi r16,0x32
sts ADCB_REFCTRL, r16 ; use AREFB as reference voltage, enable
bandgap
ldi r16, 0x01 ; select Event channel 0 to trigger ADCB
channel 0
sts ADCB_EVCTRL, r16 ; conversion
05/13/2025 62
ldi r16, 0x03 ; clkperi ÷ 32
sts ADCB_PRESCALER, r16 ; set ADC clock to 1 MHz
ldi r16,0x0F ; clear all ADC IF flags
sts ADCB_INTFLAGS, r16
ldi r16, 0x08
sts ADCB_CH0_MUXCTRL, r16 ; select PB1 pin as positive input
ldi r16, 0x03
sts ADCB_CH0_INTCTRL, r16 ; set ADCB channel 0 interrupt to high
level
ldi r16, 0x01
sts ADCB_CH0_CTRL, r16 ; select single-ended positive input mode
call initTCF1 ; configure timer 1 on PORTF to overflow every
250 ms
call
05/13/2025 initEventCH0 ; link timer 1 on PORTF overflow event to event63
;
------------------------------------------------------------------------------------------------------------
-------------------------------------
; This subroutine configures Timer 1 associated with PORTF to count with the
clock
; clk_PER/256 and set the period to 31250 (count from 0 to 31249).
Overflow in 250 ms.
;
------------------------------------------------------------------------------------------------------------
--------------------------------------
initTCF1:
ldi r16, 0
sts TCF1_CTRLB, r16
ldi r16, low(31249)
sts TCF1_PER, r16
ldi r16, high(31249)
sts TCF1_PER+1, r16
clr r16
sts TCF1_CNT, r16 ; force TCF1 counter 1 to count up from 0
sts TCF1_CNT+1, r16
05/13/2025 ldi r16, 0x06 ; enable TCF1 to count with clock input set to 64
;
----------------------------------------------------------------------------------------------------------
------------------------
; This subroutine configures Timer 1 overflow associated with PORTF as
event
; multiplexer input to event channel 0.
;
----------------------------------------------------------------------------------------------------------
------------------------
initEventCH0:
ldi r16, 0xF8 ; configure Timer 1 overflow on PORTF
sts EVSYS_CH0MUX, r16 ; as source for event channel 0
ret
;
----------------------------------------------------------------------------------------------------------
------------------------
; This is the TCF1 overflow interrupt service routine.
;
----------------------------------------------------------------------------------------------------------
------------------------
05/13/2025 65
;
---------------------------------------------------------------------------------------------------------------------
----------------
; The following subroutine creates a delay that is a multiple of 1 us.
;
---------------------------------------------------------------------------------------------------------------------
----------------
delayby1us:
uslp1: ldi r20, 4 ; 1 CPU clock cycle
uslpi: push r0 ; 2 CPU cycles
pop r0 ; 2 CPU cycles
dec r20 ; 1 CPU cycle
brne uslpi ; 2 (1) CPU cycles
dec r16 ; 1 CPU cycle
brne uslp1 ; 2 (1) CPU cycles
ret ; 2 CPU cycles
.include "sysClock_xmega.asm"
.include "delays_xmega.asm"
05/13/2025 66
Example 12.8 Write a function to initialize ADCA to operate with
the following settings, assuming that the XMEGA128A1U is running
with a 32-MHz processor clock:
Enable ADCA
Unsigned input mode, disable free-running, 12-bit resolution,
result right justified.
Select the AREFA pin input as its reference voltage
Start ADC conversion every 250 ms (triggered by TCF1 Timer
overflow). Assign timer TCF1 overflow to be event channel 0
input.
Set ADC clock prescaler to 32
05/13/2025 67
Example 12.8—(continued)
Use ADC1 pin as positive input of ADCA channel 0
Select signed single-ended mode
Set ADCA channel 0 to interrupt with high priority but not
enable it
Set up the compare register so that the ADCA interrupts the CPU
whenever the ADC result is higher than 2.4 V (let the AREFA =
2.7 V).
05/13/2025 68
Solution:
The ADC result corresponding to 2.4 V is 2.4 × 4095 / 2.7 = 3640 = 0xE38.
The subroutine that performs the specified configuration is as follows:
initADCA_CH0:
ldi r16, 0x01 ; enable ADCA module
sts ADCA_CTRLA, r16
ldi r16, 24
call delayby1us ; wait for 24 us until ADCA is ready
ldi r16, 0x10
sts ADCA_CTRLB, r16 ; signed, single conversion mode, 12-bit
resolution
ldi r16, 0x22 ; use AREFA as reference voltage, enable
bandgap
sts ADCA_REFCTRL, r16 ; disable temperature sensor
ldi r16, 0x03 ; set ADC clock prescaler to 32
sts ADCA_PRESCALER, r16 ; and hence set ADC clock to 1 MHz
ldi r16, 0x01 ; select Event channel 0 to trigger ADCA channel
0
sts ADCA_EVCTRL, r16 ; conversion
ldi
05/13/2025 r16,0x0F ; clear all ADC IF flags 69
ldi r16, 0x08
sts ADCA_CH0_MUXCTRL, r16 ; select ADC1 pin as positive input
ldi r16, 0x0F ; set ADCA channel 0 compare result above
threshold
sts ADCA_CH0_INTCTRL, r16 ; interrupt to high priority
ldi r16, 0x38 ; set compare thresh to 2.4 V
sts ADCA_CMP, r16 ; “
ldi r16, 0x0E ; “
sts ADCA_CMP+1, r16 ; “
call initTCF1
call initEventCH0 ; make TCF1 overflow as the source for event
CH0
ldi r16, 0x01
sts ADCA_CH0_CTRL, r16 ; select single-ended input mode
ret
05/13/202 70
5
;
-----------------------------------------------------------------------------------------------------------------------
--------------
; This subroutine configures Timer 1 associated with PORTF to count with the clock
; clk_PER/256 and set the period to 31250 (count from 0 to 31249).
;
-----------------------------------------------------------------------------------------------------------------------
--------------
initTCF1: ldi r16, 0
sts TCF1_CTRLB, r16 ; timer normal mode
ldi r16, low(31249) ; overflow every 250 ms
sts TCF1_PER, r16 ; “
ldi r16, high(31249) ; “
sts TCF1_PER+1, r16 ; “
clr r16
sts TCF1_CNT, r16 ; force TCF1 counter 1 to count up from 0
sts TCF1_CNT+1, r16
ldi r16, 0x06 ; enable TCF1 to count with clk_PER/256
sts TCF1_CTRLA, r16 ; "
ldi r16, 3
05/13/2025 71
sts TCF1_INTCTRLA, r16 ; enable TCF1 overflow interrupt
;
----------------------------------------------------------------------------------------------------------
------------------------
; This subroutine configures Timer 1 overflow associated with PORTF as
event
; multiplexer input to event channel 0.
;
----------------------------------------------------------------------------------------------------------
------------------------
initEventCH0:
ldi r16, 0xF8 ; configure Timer 1 overflow on PORTF
sts EVSYS_CH0MUX, r16 ; as source for event channel 0
ret
;
----------------------------------------------------------------------------------------------------------
------------------------
; This is the TCF1 overflow interrupt service routine.
;
----------------------------------------------------------------------------------------------------------72
05/13/2025
Using the Analog Temperature Sensor TC1047A
TC1047A is a 3-pin analog temperature sensor with voltage
output.
Range of temperature that can be measured: -40oC to 125oC.
Power supply: 2.7 to 5.5 V
Voltage output range is 0.1 to 1.75 V for temperature range -
40oC to 125oC.
Voltage slope output response is 10 mV/oC
05/13/2025 73
VOUT
1.75
VSS
1.4
3
0.9
TC1047A
0.5
1 2
0.1
VDD VOUT
-40 0 40 90 125
Temperature
Figure 13.26 TC1047A VOUT vs. temperature characteristic
05/13/2025 74
Circuit for Temperature Measurement
3.3 V 3.3 V
VDD
VDD
VOUT ADC0/PA0
TC1047A XMEGA128A1
VSS GND
05/13/2025 75
Example 12.9 Write a program to measure the temperature using the circuit
shown in Figure 13.27 once every 100 ms.
Solution:
We will use VCC/1.6 (= 2.0625V) as the ADC VREF. If we extrapolate the
temperature to -50oC, the span of voltage output from the TC1047A is expanded
to 1.75 V (from 0V to 1.75 V). The ADC result range will be from 0 (offset) to
2047 × 1.75 2.0625 = 1737.
By dividing the ADC result by 9.93 (1737 175 = 9.93), the conversion result
can be translated back to temperature reading. To divide the ADC result by
9.93, we first multiply the ADC result by 10 and then divide the resultant
product by 99.
05/13/2025 76
.include <atxmega128A1def.inc>
.dseg
.org 0x2000
tBuf: .byte 10 ; used to hold D2D1D0.F1oC\0
.cseg
.org 0x00
jmp start
.org 0xF6
start: ldi r16, low(RAMEND)
sts CPU_SPL, r16
ldi r16, high(RAMEND)
sts CPU_SPH, r16
call setCPUClkto32Mwith32MIntOSC
call initADCA_CH0
forever: call initBuf
TMLoop: ldi r16, 0x81 ; start temperature conversion
in unsigned
sts ADCA_CH0_CTRL, r16 ; single-ended mode
WCloop: lds r16,ADCA_INTFLAGS ; check interrupt
flags
05/13/2025
sbrs r16, ADC_CH0IF_bp ; skip if CH0 ADC conversion is complete 77
lds r16, ADCA_CH0RES ; read ADC result to r16:r17
lds r17, ADCA_CH0RES+1
ldi r18, 10 ; Multiply ADC_Result by 10
clr r19 ; "
call mul16U ; “
movw r16, r22 ; transfer product to r16:r17 (product is 16-bit
only)
ldi r18, low(99) ; place divisor in r18:r19
ldi r19, high(99) ; "
call div16U ; convert ADC result back to temperature
movw r2, r24 ; save integer part of temperature in r2:r3
movw r16, r22 ; transfer remainder to r16:r17
ldi r18, 10 ; prepare to compute fractional digit
clr r19 ; "
call mul16U ; "
movw r16, r22 ; transfer product to r16:r17
ldi r18, 99 ; place divisor in r18:r19
clr r19 ; "
call div16U ; compute fraction digit
05/13/2025 78
cpi r22, 50 ; round up the fractional digit
brlo toASCII ; branch to convert fractional digit to ASCII
inc r24 ; round up fractional digit
cpi r24, 10 ; "
brlo toAscii ; convert fraction digit to ASCII code
inc r2 ; round up integer digit
clr r24 ; reset fractional digit to 0
toASCII: ldi r18, 0x30
mov r5, r18 ; save 0x30 in r5
add r24, r5 ; convert fractional digit to ASCII code
sts tBuf+4, r24
movw r26, r2 ; transfer integer part to r26:r27 (subtract 50 from
sbiw r26, 50 ; integer part
movw r16, r26 ; “
sbrs r17, 7
rjmp separ ; if result positive, separate integer digits
05/13/2025 79
ldi r19, 0x2D
sts tBuf, r19 ; store the minus sign
com r16 ; take two's complement of integer part
com r17 ; "
movw r26, r16 ; "
adiw r26, 1 ; "
movw r16, r26 ; "
cpi r24, 0x30 ; is fractional equal to 0
breq separ ; yes, then separate digits
ldi r25, 0x3A ; take the 10's complement of the
sub r25, r24 ; fractional digit
add r25, r5 ; and convert it (r5 holds 0x30) to ASCII code
sts tBuf+4, r25 ; save it in buffer
dec r16 ; decrement integer part by 1
05/13/2025 80
separ: ldi r18, 10 ; divide by 10
clr r19
call div16U
add r22, r5 ; convert one's digit to ASCII
sts tBuf+2, r22 ; "
cpi r24, 0
breq done
movw r16, r24 ; transfer quotient to r16:r17
ldi r18, 10
clr r19
call div16U
add r22, r5 ; convert ten's digit to ASCII
sts tBuf+1, r22
cpi r24, 0
breq done
ldi r24, 0x31 ; hundred's digit is 1
sts tBuf, r24
done: ldi r16,1
call delayby100ms
jmp forever
05/13/2025 81
; --------------------------------------------------------------------------------------
; This subroutine initialize temperature buffer.
; --------------------------------------------------------------------------------------
initBuf:ldi r16,0x20 ; initialize tBuf
sts tBuf, r16 ; "
sts tBuf+1, r16 ; "
ldi r16, 0x30 ; "
sts tBuf+2, r16 ; "
sts tBuf+4, r16 ; "
ldi r16, 0x2E ; place period (.) in tBUF + 1
sts tBuf+3, r16 ; “
clr r16
sts tBuf+7, r16 ; terminate the buffer with a NULL character
ldi r16, 223
sts tBuf+5, r16 ; store degree character
ldi r16, ‘C’ ; store letter C
sts tBuf+6, r16 ; "
ret
05/13/2025 82
;
----------------------------------------------------------------------------------------------------------------
----------------------------
; This subroutine initializes ADCA to 12-bit resolution, ADC0 input in single-
ended
; unsigned mode, use INTVCC as reference voltage.
;
----------------------------------------------------------------------------------------------------------------
----------------------------
initADCA_CH0:
ldi r16, 0x01 ; enable ADCA module
sts ADCA_CTRLA, r16 ; "
ldi r16, 24 ; wait for 24 us until ADCA is ready
call delayby1us ;"
ldi r16, 0x10 ; configure ADCA to operate in signed,
sts ADCA_CTRLB, r16 ; single conversion mode, 12-bit resolution
ldi r16, 0x12 ; select INTVCC as reference voltage
sts ADCA_REFCTRL, r16 ; and enable bandgap, disable
temperature sensor
clr r16 ; disable any event input
05/13/2025 sts ADCA_EVCTRL, r16 ; " 83
ldi r16, 0x03 ; set ADC clock to 1 MHz
sts ADCA_CH0_MUXCTRL, r16 ; to ADCA channel 0
ldi r16, 0x03
sts ADCA_CH0_INTCTRL, r16 ; set ADCA channel 0 interrupt to high
level
ldi r16, 0x01
sts ADCA_CH0_CTRL, r16 ; select single-ended input mode
ret
.include "sysClock_xmega.asm"
.include "delays_xmega.asm"
.include "div16U.asm"
.include "mul16U.asm"
05/13/2025 84
Example 12.10The output of a potentiometer is connected to PA1 pin. The
voltage range of the potentiometer is assumed to be from 0 V to 3.3/1.6V (= 2.0625
V). Write a program to measure this voltage once every 100 ms.
XMEGA128A1
3.3 V
2.0625 V
PA1
05/13/2025 85
Solution:
We will use INTVCC (=2.0625V) as the ADC reference
voltage. The voltage range 0 ~ 2.0625V will be converted to 0
~ 2047. To convert from ADC result to voltage, we need to
divide the ADC result by 992 (= 2047/2.0625).
05/13/2025 86
.include <atxmega128A1def.inc>
.dseg
.org 0x2000
tBuf: .byte 6 ; to hold d0.f1V\0
.cseg
.org 0x00
jmp start
.org 0xF6
start: ldi r16, low(RAMEND)
sts CPU_SPL, r16
ldi r16, high(RAMEND)
sts CPU_SPH, r16
call setCPUClkto32Mwith32MIntOSC
call initADCA_CH0
forever: call initVBuf
TMLoop: ldi r16, 0x81 ; start voltage conversion in
signed
sts ADCA_CH0_CTRL, r16 ; single-ended mode
05/13/2025 87
WCloop: lds r16, ADCA_INTFLAGS ;
sbrs r16, ADC_CH0IF_bp ; skip if CH0 ADC complete
rjmp WCloop
lds r16, ADCA_CH0RES ; read ADC result to r16:r17
lds r17, ADCA_CH0RES+1
ldi r18,low(992)
ldi r19,high(992)
call div16U ; convert to voltage
mov r2,r24 ; save integer part of voltage in r2
movw r16,r22 ; transfer remainder to r16:r17
ldi r18,10 ; prepare to compute fractional digit
clr r19 ; "
call mul16U ; "
movw r16,r22 ; transfer product to r16:r17
ldi r18,low(992) ; place divisor in r18:r19
ldi r19,high(992) ; "
05/13/2025 88
call div16U ; compute fraction digit
ldi r20, high(496)
cpi r22, low(496) ; check if round up is needed
cpc r23, r20 ; “
brlo toASCII ; branch to convert fractional digit to ASCII
inc r24 ; round up fractional digit
cpi r24, 10 ; "
brlo toASCII ; convert fraction digit to ASCII code
inc r2 ; round up integer digit
clr r24 ; reset fractional digit to 0
toASCII:ldi r18, 0x30
add r24, r18 ; convert fractional digit to ASCII code
sts tBuf+2, r24
add r2,r18 ; convert integer digit to ASCII
sts tBuf, r2 ; and save it in tBuf
ldi r16,1
call delayby100ms
jmp forever
05/13/2025 89
;
---------------------------------------------------------------------------------------------------------------------
-
; This subroutine initialize temperature buffer.
;
---------------------------------------------------------------------------------------------------------------------
-
initVBuf: ldi r16,0x30 ; initialize tBuf
sts tBuf, r16 ; "
sts tBuf+2, r16 ; "
ldi r16, 0x2E
sts tBuf+1, r16
ldi r16,'V'
sts tBuf+3,r16
clr r16
sts tBuf+4, r16 ; terminate the buffer with a NULL character
ret
.include "sysClock_xmega.asm"
.include "delays_xmega.asm"
05/13/2025 .include "div16U.asm" 90
.include "mul16U.asm"
initADCA_CH0:
ldi r16, 0x01 ; enable ADCA module
sts ADCA_CTRLA, r16 ; "
ldi r16, 24 ; wait for 24 us until ADCA is ready
call delayby1us ; "
ldi r16, 0x10 ; configure ADCA to operate in signed,
sts ADCA_CTRLB, r16 ; single conversion mode, 12-bit resolution
ldi r16, 0x12 ; select INTVCC as reference voltage
sts ADCA_REFCTRL, r16 ; and enable bandgap, disable temperature sensor
clr r16 ; disable any event input
sts ADCA_EVCTRL, r16 ; "
ldi r16, 0x03 ; set ADC clock to 1 MHz
sts ADCA_PRESCALER, r16 ; "
ldi r16,0x0F ; clear all ADC IF flags
sts ADCA_INTFLAGS, r16 ; "
ldi r16, 0 ; select ADC0 pin as positive input
sts ADCA_CH0_MUXCTRL, r16 ; to ADCA channel 0
ldi r16, 0x01
sts ADCA_CH0_CTRL, r16 ; select single-ended input mode
ldi r16, 0x03
sts ADCA_CH0_INTCTRL, r16 ; set ADCA channel 0 interrupt to high level
ret
05/13/2025 91