[AVR] ATtiny24에서 ADC로 전압 받기

jalju·2022년 5월 23일
0

아두이노 & AVR

목록 보기
1/2

아두이노 관련해서 만지고 있는데 아두이노 스케치가 아닌 Microchip studio에서 adc로 전압을 받게 되는 경우가 생겼다. 근데 여러자료들을 찾아도 내 생각대로 안돼서 고생하다가 결국 해결하게 되었다.

ADC를 받는 과정은 단순하게 정리하면

  1. ADC를 받아올 때 상대적으로 비교할 전압의 유형과 전압을 받아올 핀을 정한다.
  2. ADC Frequency를 정하고 전환시 가져올 값의 정렬 방식과 trigger source를 설정한다.
  3. Conversion를 시작한다.
  4. 전압 값을 변수에 받아온다.

이다.

전압의 유형을 정하려면 Register의 비트 값을 설정 해야한다. 그럼 설정 해야하는 Register가 뭔지 알아보자.

이 문서는 AVR에서 제공하는 공식 문서다. ATTINY24에 대한 문서이다.

1번의 비교할 전압의 유형을 정하는 경우는 위 사진에서 볼 수 있듯이, ADMUX의 REFS1,REFS0로 정할 수 있다. 위와 같이 표로 정리 되어 있는데 두 비트에 00를 넣으면 Vcc로 들어오는 전압을 비교전압으로 쓰겠다는 말이다.
01를 넣으면 PA0(AREF)로 들어오는 전압 값을 비교전압으로 쓰는 것이다. 10를 넣으면 칩 자체 내부에 1.1v를 비교전압으로 쓰겠다는 말이다.

이제 받아올 핀을 정해야한다. ADC를 지원하는 핀은 MCU마다 다르다. pin conpigurations에 ADCx(x는 숫자)가 해당되는 경우이다.

이제 핀을 어떻게 설정해야 내가 원하는 핀에서 값을 읽어오는 지는 공식문서에 영어로 친절하게 표로 만들어서 알려준다. 밑에 있는 예제에서 나는 ADC3에서 값을 읽어왔다.

2번은 ADC의 인가되는 클럭의 분주비를 정하는 건데 ADC 클록으론 50~200[kHz]의 주파수가 적절하다고 한다. 그럼 분주비를 정하기 위해선 또 표를 봐야한다.


이번에는 ADCSRA라는 Register의 비트를 바꿔야한다. 본인이 설정한 값에 맞춰 설정하자.
이제 값을 받아와서 비트에 정렬되는 방식을 정하고 trigger source를 정하면 된다. trigger source에 대해선 잘 몰라서 https://eunbit.tistory.com/12 여기 사이트를 참고하면 된다. 나도 이번 기회에 알게 되었다.
이제 전환을 하게 되면 전환된 값은 ADCL, ADCH라는 Register에 저장된다.

값을 넣어지는 방식이 두가지인데 왼쪽으로 정렬 되는 방법과 오른쪽으로 정렬 되는 방법이다.
원하는 방식을 사용하면 된다. ADCSRB에 있는 ADLAR에 값을 넣으면 된다.

3번은 이제 설정한 분주비와 비교전압, 전환 값 정렬 방식, trigger source를 토대로 변환을 한다. 보통 나는 single conversion를 자주 사용하고 left로 값을 채워넣고 free running mode를 사용한다. 밑의 예제도 이를 사용했다.

4번은 이제 내가 원하는 변수에 값을 넣어 사용하면 된다. 이제 ADC로 넘어오는 값은 특정 공식에 의해 산출되어 넘어온다. 이 공식은 공식문서에 친절히 설명되어 있다.

V(ref)가 비교전압이고 V(in)이 내가 설정한 ADC값을 받아오는 포트다. 들어오는 Volt값을 알고 싶다면, ADC로 넘어온 값 * V(ref) / 1024하면 된다.

부족한 내용이 많지만 아는 만큼 적어봤다. 밑의 코드는 내가 쓴 예제이다.

int main(void)
{	
	DIDR0 = (1<<ADC3D);							
	ADMUX =  (1<<MUX1) | (1<<MUX0);					
	ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);	
	ADCSRB = (0<<ADLAR);						
	while(1)
    {
    	ADCSRA |= (1<<ADSC);				
		while((ADCSRA & (1<<ADIF)) == 0);	// Wait for completion of ADC

		ADCSRA |= (1<<ADIF);				// Clear ADC Interrupt flag

		value = ADCL;
		value = ((ADCH)<<8)|value; 
    }
}
profile
https://www.acmicpc.net/user/dlckswn334

0개의 댓글