Analog Interfacing. These lecture notes created by Dr. Alex Dean, NCSU. In These Notes. Analog to Digital Converters ADC architectures Sampling/Aliasing Quantization Inputs M30626 ADC Peripheral Digital to Analog Conversion. Why It’s Needed.
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
These lecture notes created by Dr. Alex Dean, NCSU
Voltages
V_ref
111..111
111..110
111..101
111..100
V_sensor
ADC_Code
000..001
Ground
000..000
The Big PictureV_ref
// Your software
ADC_Code = ad0;
V_sensor = ADC_code*V_ref/1023;
Pressure_kPa = 250 * (V_sensor/V_supply+0.04);
Depth_ft = 33 * (Pressure_kPa – Atmos_Press_kPa)/101.3;
Analog to Digital Converter
PressureSensor
AirPressure
ADC_Code
V_sensor
Comparator
A/D Converter
Vref
Vin0
0
1
0
1
0
Vin1
Vin
Clock
time
Waveform Sampling and QuantizationThe ideal transfer function A/D converter is a stairstep function.
Consider a 2bit ADC
0 to 4 V input
LSB = 4/22 = 1 V
Red line
Truncation
Maximum error is 1 LSB or + 0 LSB
Blue line
Rounding
Maximum error in conversion is usually 1/2 bit.
Half as much error if we limit range to Vref(12N/2)
“3.0 V”
“2.0 V”
“1.0 V”
“0.0 V”
Transfer Function11
1 LSB
10
Output Code
01
00
1.0 V
4.0 V
3.0 V
2.0 V
Input Voltage
General Equation
n = converted code
Vin= sampled input voltage
V+ref = upper end of input voltage range
Vref = lower end of input voltage range
N = number of bits of resolution in ADC
Simplification with Vref = 0 V
(
)
2
N
V
=
+
in
n
1
/
2
ê
ú
V
ê
ú
ë
û
+
ref
10
3
.
30
v
2
(
)
=
+
=
n
1
/
2
676
ê
ú

N
V
V
2
5
v
ë
û

in
ref
=
+
n
1
/
2
ê
ú

V
V
ê
ú
ë
û
+

ref
ref
X = I
floor function: nearest integer I such that I <= X
û
ë
A comparator is used at each level to determine whether the voltage is lower or higher than the level.
The series of comparator outputs are encoded to a binary number in digital logic (a priority encoder)
Components used
2N resistors
2N1 comparators
Note
This particular resistor divider generates voltages which are not offset by ½ bit, so maximum error is 1 bit
We could change this offset voltage by using resistors of values R, 2R, 2R ... 2R, 3R (starting at bottom)
7/8 V
6/8 V
5/8 V
4/8 V
3/8 V
2/8 V
1/8 V
A/D – Flash Conversion1V
Comparators
R
+
1
R

+
1
R

+
1
R

+
R
3
Encoder
0

+
0
R

+
0
R

+
0
R

V
in
Slope proportional
to input voltage
SA Register holds current approximation of result
Set all DAC input bits to 0
Start with DAC’s most significant bit
Repeat
Set next input bit for DAC to 1
Wait for DAC and comparator to stabilize
If the DAC output (test voltage) is smaller than the input then set the current bit to 1, else clear the current bit to 0
T
T
4
6
T
5
T
3
T
2
T
1
know 10011x, try 100111
know 1001xx, try 100110
know 100xxx, try 100100
know 10xxxx, try 101000
know 1xxxxx, try 110000
know 100110. Done.
ADC  Successive Approximation Conversion111111
Test voltage(DAC output)
AnalogInput
100110
100100
Voltage
100000
know xxxxxx, try 100000
000000
Start of
Conversion
Time
In other cases, peak capture or sampling at a specific point in time necessitates a sampling device.
This function is accomplished by a sample and hold device as shown to the right:
These devices are incorporated into some A/D converters
Sample and Hold DevicesfAD
32.768 kHz crystal oscillator here
1024 Hz
24 or 12 MHz
3 MHz
0.75 MHz
24 MHz
12 MHz ceramic or crystal oscillator here
PLL doubles frequency
24 MHz
#include "qsk_bsp.h"
#include "stdio.h"
#include "string.h"
#define INPUT (0)
unsigned position_code;
void main(void)
{
char buf[9];
mcu_init(); // Initialize MCU
adc_init(); // ADC too
InitDisplay(); // LCD too
while (1) {
adst = 1;
while (adst)
;
position_code = ad0 & 0x03ff;
sprintf(buf, "%d", position_code);
DisplayString(LCD_LINE1,“ ");
DisplayString(LCD_LINE1, buf); // display position
}
}
void adc_init(void) {
pd10_0 = INPUT; // To use channel 0 on P10 group as input
/* clock selection: 24 MHz system clock, 6 MHz phiAD > divide by 4
cks bits are 0 0 0 */
// ADCON 0
ch0 = 0; // channel 0
ch1 = 0;
ch2 = 0;
md0 = 0; // one shot
md1 = 0;
cks0 = 0; // divide clock by 4
// ADCON 1
trg = 0; // SW trigger
md2 = 0; // one shot
bits = 1; // 10bit conversion
cks1 = 0; // divide clock by 4\
vcut = 1; // connect reference voltage
// ADCON 2
smp = 1; // use sample and hold
adgsel0 = 0; // select port P10 group
adgsel1 = 0;
cks2 = 0; // divide clock by 4
}
adcon0 = 0x88;
adcon1 = 0x28;
adcon2 = 0X01;
adst = 1; // Start a conversion here
TempStore = ad0 & 0x03ff;
D/A Converter
0
1
0
1
Vout
adic = 0X01;
/* 00000001; /* Enable the ADC interrupt
______interrupt priority select bit 0
_______interrupt priority select bit 1
________interrupt priority select bit 2
_________interrupt request bit
__________reserved */
_asm (" fset i") ; // globally enable interrupts
adst = 1; // Start a conversion here
while (1){} // Program waits here forever
}
#pragma INTERRUPT ADCInt // compiler directive telling where
// the ADC interrupt is located
void ADCInt(void){
TempStore = ad0 & 0x03ff;// Mask off the upper 6 bits of
// variable leaving only the result
} // in the variable itself
To use interrupts, the ADC interrupt vector needs to point to the function. The interrupt vector table is near the end of the startup file “sect30.inc”. Insert the function label “_ADCInt” into the interrupt vector table at vector 14 as shown below.
. . .
.lword dummy_int ; DMA1(for user)(vector 12)
.lword dummy_int ; Key input interrupt(for user)(vect 13)
.glb _ADCInt
.lword _ADCInt ; AD(for user)(vector 14)
.lword dummy_int ; uart2 transmit(for user)(vector 15)
.lword dummy_int ; uart2 receive(for user)(vector 16)
. . ..
#pragma INTERRUPT ADCInt // compiler directive telling where
// the ADC interrupt is located
void ADCInt(void){
TempStore = ad0 & 0x03ff; // Mask off the upper 6 bits of
// variable leaving only the result
} // in the variable itself