주변 환경에서 얻을수 있는 데이터들은 모두 아날로그 데이터이다.
하지만 우리가 사용하는 전자기기들의 데이터들은 0과 1로만 이루어진
디지털 신호로만 이루어져있다.
떄문에 이러한 자연의 아날로그 신호를 전자기기가 처리할 수 있게끔 변환 시켜주는 방법이 바로 아날로그-디지털 변환기(Analog-Digital Converter, ADC)라고 한다,
ATmega128은 아날로그 데이터를 디지털 데이터로 변환하기 위한 비트가 10개가 있다.
즉 전압을 0~1023(=2^10-1)사이의 디지털 값으로 변환 할수 있는 것이다
ADC 채널은 8개로 8개의 아날로그 출력장치를 ATmega128에 연결한수 있다. 하지만 8개의 채널은 하나의 AD 변환기에 멀티플렉스(Multiplexer, MUX)로 연결되어 있으므로 한번에 하나의 아날로그 입력만 변환 할 수있다.
8개의 채널은 포트 F의 PF0~PF7까지 있다.
ADC를 함에 있어 고려할점 중 하나가 바로 몇 볼트를 1023으로 변환할 것인가 이다. 기준 전압은 AD 변환에 있어서 최대갓으로 변환되는 전압을 의미한다. ATmega128에서는 기준 전압으로 AVCC(Analog VCC), AREF(Analog Reference), 내부 2.56V중 하나를 선택하여 사용할 수 있다.
AVCC는 보통 VCC와 동일하게 5V가 가해진다. 5V이외의 기준을 잡고자 한다면, AREF 핀에 5V 이하의 전압을 연결해주면 된다. 그외 내부 2.56V를 기준으로 사용할 수 있다.
예를 들어 5V가 기준이라고 했을때
이를 나누면 5/1023= 4.89mV 씩의 차이마다 변화를 인식한다.
하지만 주의할 점이 있다.
낮은 해상도의 경우 보다 높은 ADC 칩을 사용하면 해결할 수 있다.
잡음의 경우에는 차동 입력(differential input)을 통해 보완할 수 있다. 신호의 크기를 접지(GND)와 비교하는 방식인 단일(Single-Ended) 입력과 달리 차동 입력은 2개의 핀 입력((+)입력과 (-)입력)으로 신호를 받아 이들의 차이를 ADC의 입력으로 받아 들이는 방식이다.
단일입력의 경우 잡음또한 그래도 반영되는것과 달리, 차동 입력은 2개의 핀에 잡음이 공통으로 들어올경우 잡음이 상쇄되는 효과를 얻을수 있다.
물론 공통 잡음이 입력되는 공통 모드 잡음(common mode noise)이 아닌 경우에는 잡음제거효과를 기대할 수 없다.
위 둘의 또 다른 차이점으론 디지털로 변환 할수 있는 범위의 차이이다.
단일의 경우 GND를 기준으로 하므로 변환할 수 있는 최소값이 항상 0V 이다. 따라서 단일입력에서 2.5V기준 전압을 사용할 경우 변환 가능 범위가 0V~2.5V라는 위미이다. 하지만 차동의 경우 2V~4.5V 범위의 전압을 변환 할수 있으며, 이때는 2V의 값이 0에 해당된다. 하지만 차동의 경우 각 입력에 가해지는 전압은 GND와 AVCC범위 내에 있어야 한다.
AD 변환한 디지털 데이터를 저장하는 레지스터이다.
ATmega128에서의 레지스터는 모드 8비트를 지원한다. 때문에 변환된 데이터의 값은 2개의 레지스터에 나눠져서 저장된다.
ADCH와 ADCL 16개의 비트중 6개의 비트는 사용하지 않으며, 데이터 정렬 방식에 따라서 상위 또는 하위 6개의 비트 비사용 여부가 정해진다.
기본값은 우측 정렬이다.
비트 | 15 | 14 | 13 | 12 | 12 | 10 | 9 | 8 |
---|---|---|---|---|---|---|---|---|
ADCH | - | - | - | - | - | - | ADC9 | ADC8 |
ADCL | ADC7 | ADC6 | ADC5 | ADC4 | ADC3 | ADC2 | ADC1 | ADC0 |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
비트 | 15 | 14 | 13 | 12 | 12 | 10 | 9 | 8 |
---|---|---|---|---|---|---|---|---|
ADCH | ADC9 | ADC8 | ADC7 | ADC6 | ADC5 | ADC4 | ADC3 | ADC2 |
ADCL | ADC1 | ADC0 | - | - | - | - | - | - |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | REFS1 | REFS0 | ADLAR | MUN4 | MUX3 | MUX2 | MUX1 | MUX0 |
초기값 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
이름 | 비트 | 설명 |
---|---|---|
REFS1 | 7 | AD변환을 위한 기준 전압과 입력 채널 선택을 위한 레지스터 |
REFS0 | 6 | - |
ADLAR (ADC Left Adjust Result) | 5 | 1 : 좌측 정렬 0 : 우측 정렬 |
MUN4 | 4 | ADC에 입력으로 가해지는 전압을 선택하는 레지스터 ATmega128은 단일, 차동을 지원한다. 또한 차동 입력 시에 이득을 정할 수 있다. |
MUX3 | 3 | |
MUX2 | 2 | |
MUX1 | 1 | |
MUX0 | 0 |
REFSn 표
REFS1 | REFS0 | 설명 |
---|---|---|
0 | 0 | 외부 AREF 핀 입력을 기준 전압으로 사용 |
0 | 1 | 외부 AVCC 핀 입력을 기준 전압으로 사용 |
1 | 0 | |
1 | 1 | 내부 2.56V를 기준 전압으로 사용 |
ADLART | 설명 |
---|---|
0 | 우측 정렬(기본값) |
1 | 좌측 정렬 |
MUX | 단일 입력 | 차동 + | 차동 - | 이득 |
---|---|---|---|---|
00000 | ADC0 | |||
00001 | ADC1 | |||
00010 | ADC2 | |||
00011 | ADC3 | |||
00100 | ADC4 | |||
00101 | ADC5 | |||
00110 | ADC6 | |||
00111 | ADC7 | |||
01000 | ADC0 | ADC0 | 10x | |
01001 | ADC1 | ADC0 | 10x | |
01010 | ADC0 | ADC0 | 200x | |
01011 | ADC1 | ADC0 | 200x | |
01100 | ADC2 | ADC2 | 10x | |
01101 | ADC3 | ADC2 | 10x | |
01110 | ADC2 | ADC2 | 200x | |
01111 | ADC3 | ADC2 | 200x | |
10000 | ADC0 | ADC1 | 1x | |
10001 | ADC1 | ADC1 | 1x | |
10010 | ADC2 | ADC1 | 1x | |
10011 | ADC3 | ADC1 | 1x | |
10100 | ADC4 | ADC1 | 1x | |
10101 | ADC5 | ADC1 | 1x | |
10110 | ADC6 | ADC1 | 1x | |
10111 | ADC7 | ADC1 | 1x | |
11000 | ADC0 | ADC2 | 1x | |
11001 | ADC1 | ADC2 | 1x | |
11010 | ADC2 | ADC2 | 1x | |
11011 | ADC3 | ADC2 | 1x | |
11100 | ADC4 | ADC2 | 1x | |
11101 | ADC5 | ADC2 | 1x | |
11110 | 1.23V(V bg) | - | - | - |
11111 | 0V(GND) | - | - | - |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | ADEN | ADSC | ADFR | ADIF | ADIE | ADPS2 | ADPS1 | ADPS0 |
초기값 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
이름 | 비트 | 설명 |
---|---|---|
ADEN | 7 | ADC 활성화 비트 |
ADSC | 6 | AD변환을 시작하도록 하는 비트 단일모드에서는 각 변환을, 프리러닝 모드에서는 첫 번째 변환을 시작하기 위해 사용한다.단일모드에서는 변환이끝나면 알아서 0으로 초기화 된다. |
ADFR (ADC Left Adjust Result) | 5 | 0 : 단일 변환 모드 1 : 프리러닝 모드 |
ADIF | 4 | AD 변환이 종료되고 데이터 레지스터가 업데이트 되면 1로 세트된다. |
ADIE | 3 | AD 변환이 끝났을때 인터럽트 발생 허용 비트이다 이떄 실제로는 SREG 레지스터의 I 가 세트되어 있어야 한다. 즉 AD 변환이 끝나고 ADIF 세트 되었을때 ADIE와 SREG의 I가 세트 되었을때 AD 변환 완료 인터럽트가 발생한다. |
ADPS2 | 2 | - |
ADPS1 | 1 | - |
ADPS0 | 0 | 사용되는 클럭의 분주율을 설정한다. |
ADPS2 | ADPS1 | ADPS0 | 분주율 |
---|---|---|---|
0 | 0 | 0 | 2 |
0 | 0 | 1 | 2 |
0 | 1 | 0 | 4 |
0 | 1 | 1 | 8 |
1 | 0 | 0 | 16 |
1 | 0 | 1 | 32 |
1 | 1 | 0 | 64 |
1 | 1 | 1 | 128 |
//************************************************************************
// Ex9-1.c
//************************************************************************
// ADC0 단극성 입력, 단일 변환, 128분주, VREF=AREF
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include "lcd_2_line.h"
int main(void)
{
int ADval;
double Vin, Vref=5.0;
char msg[16];
LCD_init(); // LCD 초기화
DDRF = 0x00; // 포트 F 입력
ADMUX = 0x40; // VREF=AREF, ADC0 단극성 입력
ADCSRA = 0x87; // 단일변환, 128분주
_delay_ms(5);
while(1)
{
ADCSRA = ADCSRA | 0x40; // ADSC=1 변환시작
while((ADCSRA & 0x10) == 0); // ADIF=1 ?, 변환완료 체크
ADval = (int)ADCL + ((int)ADCH << 8);
Vin = (double)ADval*Vref/1023.0; // val=(Vin*1024)/Vref
LCD_goto_XY(0, 1); // LCD 1행 1열에 표시
sprintf(msg, "ADC0 = %.2lf[V]", Vin);
LCD_write_string(msg); // LCD에 A/D 변환 결과 표시
_delay_ms(1000);
}
}