티스토리 뷰

입문

ADC(Analog to Digital Converter)

Just4Fun 2016. 4. 14. 21:20

ADC는 아날로그 입력값을 디지털값으로 변환해 주는 모듈이다.  여기서 말하는 아날로그 값이란 다름이 아니고 핀으로 인가되는 전압값을 의미한다.  이 전압값이 ARef값을 기준으로 했을때 어느정도의 비율을 가지는지 숫자로 알려주는것이 ADC인 것이다.  AVR의 ADC는 10비트 해상도를 지원한다.  이 말은 아날로그 입력전압이 GND와 같을때 0의 값을 가지고, ARef값과 같으면 2^10-1의 값을 가진다. 즉 0~1023까지의 값으로 표현된다는 의미다.  예를 들어 ARef가 5V 일때 아날로그 입력 전압이 2.5V이면 511의 값으로 표현되는 것이다.

위의 그림이 ADC 블럭이 어떻게 구성되어 있는지 설명해주는 블럭도이다.  CPU가 ADC의 동작을 제어하기 위한 레지스터는 Databus에 연결된 ADMUX, ADCSRA, ADCH/ADCL이다.  이 그림에서는 표시되어 있지는 않지만 ADCSRB레지스터도 있다.

그림이 다소 복잡하게 보일수도 있겠지만 자세히 보면 크게 두 부분으로 나누어 볼 수 있다.  ADMUX레지스터에 의해 제어되는 부분이 있는데 그림의 좌측 부분에 있는 것들이다.  AVR에는 여러개의 ADC입력핀들이 있는데 그 중에 하나를 선택하여야 한다.  또한 AREF도 선택가능하다. 이러한 선택을 ADMUX를 통해서 하는것이다.  그리고 ADC의 핵심인 Conversion Logic이 있다.  Conversion logic에서는 ADMUX에 의해 선택된 ADC 입력전압과 AREF 전압을 이용하여 입력전압 레벨을 측정하고, 그 결과를 ADCH/ADCL에 저장하는 기능을 담당한다.

AVR의 ADC가 어떻게 동작되는지 확인하기 위하여 다음과 같은 회로를 사용하겠다.

10K옴 가변저항의 가운데 핀을 PC0(ADC0)핀과 연결한다.  가변저항기의 노브를 돌리면 ADC0핀에 인가되는 전압값이 변하게 된다.  AVCC에는 VCC전원과 연결한다.  역시 회로도에는 AVR이 동작되는데 필요한 VCC와 GND 부분이 생략되어 있고, ADC결과값을 확인하기 위한 UART 연결도 생략하였다.  UART연결은 앞의 글을 참고하여 연결하기 바란다.

회로는 가변저항 하나 연결하는것 밖에 없으므로 쉽게 구성할 수 있을것이다.

ADC값을 읽기 위해서 conversion start 명령을 주어야 한다.   Conversion logic에서는 start 명령을 받으면 입력 전압을 측정하여 그 값을 ADCH/ADCL레지스터에 기록하는 것이다.  이때 한번만 ADC변환을 수행하여 값을 읽어 올 수도 있고, 계속해서 자동으로 conversion 시킬수도 있다.

먼저 single conversion 방법을 이용하여 ADC값을 한번만 읽어 오도록 하겠다.  새로운 ADC값을 읽어 오려면 매번 conversion start 명령을 주어야 한다.

Datasheet 문서에서 ADC 블럭에 있는 레지스터의 주소를 확인한다.

위의 레지스터맵을 참조하여 C프로그램에서 사용하기 위한 구조체를 만들어 보면 다음과 같이 된다.

변환이 완료되면 그 결과를 ADCH/ADCL 레지스터에 기록하는데, 반드시 ADCL 레지스터를 먼저 읽어야 한다.  ADCL레지스터를 CPU에서 읽어 오면 ADC에서는 Data레지스터에 접근이 불가능하게 된다. CPU에서 ADCH레지스터를 읽어오면 그때에 ADC가 data 레지스터를 업데이트 할 수 있게 된다.  ADC는 10비트 해상도를 가지고 있으므로 2바이트 값으로 표현된다.  이때 C프로그램에서 한번에 데이터를 읽어 오려면 11번 라인과 같이 16비트 변수로 선언하여 값을 읽으면 컴파일러가 알아서 ADCL을 읽고, 다시 ADCH를 읽어 오는 과정을 수행한다.

만약 ADC결과를 10비트 해상도까지 필요하지 않다면 ADCH값만 읽을수도 있다.  그런 경우를 위해서 8,9번 라인처럼 1바이트 레지스터 두개로 나누어 놓았다.

ADC 초기화 코드는 위와 같이 만들수 있다.  AREF는 별도의 외부 REF를 사용하지 않고 그냥 AVCC값을 사용하는 방법을 선택하였다.  4번 라인에서 ADC를 enable하였고, ADC가 안정적으로 동작할 수 있는 클럭을 제공하기 위하여 입력 클럭을 8로 나누어 주었다.  ADC는 50KHz ~ 200KHz 사이에서 안정적으로 동작된다고 문서에 나와 있다.

Conversion을 start 하기 위하여 ADCSR_A레지스터의 ADSC 비트를 set 한다.  ADC에서 conversion 이 수행중에는 ADSC값이 계속 1로 유지되다가 conversion이 끝나면 clear된다.  그러므로 while()을 사용하여 ADSC값이 clear되는지 계속 polling 한다.  conversion이 끝나면 ADCH/ADCL값을 읽어서 리턴해 준다.

setup()과 loop() 함수는 위와 같이 한다.  250msec마다 새로운 ADC값을 읽어서 화면에 출력하도록 되어 있다.  

모든 코드를 작성한 다음 보드에서 실행시켜 보자.

가변 저항값을 변경해 가며 0~1023까지의 값이 출력되는지 확인해 본다.

1024단계까지 나눌 필요 없고 256 단계의 해상도로도 충분하다면 다음과 같이 수정해 주면 된다.

3번 라인에서 ADLAR 비트를 set 해 주었고, 12번 라인에서 adc_h값을 읽어서 리턴해 주는 코드로 수정하였다.  1바이트 값만 리턴해 주어야 하므로 리턴타잎을  uint16_t에서 uint8_t로 바꾼것도 주의하여야 한다.

위의 코드로 수정하여 다시 실행해 보면 0~255까지의 ADC값을 출력할 것이다.


이번에는 자동으로 계속 ADC 변환을 수행하도록 동작시켜 보겠다.

4번 줄에서 ADATE 비트를 set 해 주었다.  그리고, 처음 한번 ADC 변환을 위하여 6번 라인에서 ADSC 비트를 set 하여 conversion을 시작하도록 하였다.  이 이후에는 계속적으로 conversion이 수행된다. 코드를 위와 같이 수정하여 가변저항의 변화에 따라 ADC값도 같이 따라 변하는지 확인해 본다.

ADC 기능은 AVR의 다른 기능에 비해서 비교적 내용이 간단하다.  그러나 이 글에서 설명되지 않은 부분도 있으므로 자세한 내용은 datasheet를 참조하여 이해하도록 하면 좋을것 같다.


main.c


입문 과정 목차

'입문' 카테고리의 다른 글

TWI(I2C)  (13) 2016.04.16
SPI  (6) 2016.04.16
타이머/카운터 - PWM(Phase Correct PWM Mode)  (0) 2016.04.12
타이머/카운터 - PWM(Fast PWM Mode)  (2) 2016.04.12
타이머/카운터 - PWM(CTC Mode)  (0) 2016.04.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함