` 마이크로프로세서설계및실습 12-13 주차강의자료
학습목표 A/D 변환기의제어방법을이해한다 능숙하게 A/D 변환기를제어할수있도록반복실습한다 2/28
아날로그 - 디지털변환회로 아날로그 - 디지털변환회로 (A/D 변환회로 ) 는, 아날로그전기신호를디지털전기신호로변환하는전자회로이다 A/D 컨버터 (ADC: Analog-to-digital converter) 라고도불린다 아날로그신호 A/D 변환 디지털신호 <A/D 변환의개념 > 3/28
<A/D 변환채널선택및단일, 차동신호선택 > 4/28 ATmega128 A/D 변환기의개요 (1/2) 연속근사방식의 10 비트분해능을갖는다 아날로그전압을 10 비트크기의 2 진수로변환한다 8 개의아날로그입력채널이있다 ADC0(PF0)~ADC7(PF7) ADMUX 레지스터를설정하여아날로그채널을선택할수있다
ATmega128 A/D 변환기의개요 (2/2) ADC 기준전압 (V REF ) A/D 변환기는 GND(0V) 부터 V REF 까지를 10 비트의 ADC 데이터레지스터에 0x00~0x03ff 까지변환시킨다 V REF 는아래세가지중하나를선택할수있다 AVCC 내부기준전압 (2.56V) 외부와연결된 AREF 핀의전압 단일신호또는차동신호의 A/D 변환이가능 단일신호 A/D 변환값 = 단일신호전압 1023 V REF (V+-V-) 증폭비 512 차동신호 A/D 변환값 = V REF <A/D 변환의잡음대책 > 정밀한 A/D 변환을하기위해서는잡음에대한대책이필요하다 5/28
6/28 ADC 관련레지스터 (1/5) ADMUX 레지스터 (ADC Multiplexer Selection Register) 초기값 REFS1,REFS0 : 기준전압을선택 ADLAR : 결과정렬방향결정 0: 오른쪽정렬 1: 왼쪽정렬 MUX4~MUX0: 아날로그채널및증폭비선택 초기값
ADC 관련레지스터 (2/5) < MUX4~MUX0 에따른아날로그채널및증폭비 > 초기값 7/28
8/28 ADC 관련레지스터 (3/5) ADCSRA 레지스터 (ADC Control and Status Register A)
9/28 ADC 관련레지스터 (4/5) A 일반적으로 ADC 클록이 50~200 khz 가되도록설정
10/28 ADC 관련레지스터 (5/5) ADCH 와 ADCL 레지스터 (ADC Data Register) 8 비트 ADCH 와 ADCL 레지스터를연결한 16 비트중 10 비트위치에 A/D 변환결과가저장된다 ADMUX 레지스터의 ADLAR = 0 일때, ADMUX 레지스터의 ADLAR = 1 일때,
11/28 ADC 인터럽트사용순서 1. VREF 초기화 ADMUX 레지스터의 REF1~REF0 설정 2. A/D 변환활성화 ADCSRA 레지스터의 ADEN 을세트 3. 알맞은 ADC 클록선택 ADCSRA 레지스터의 ADPS2~ADPS0 설정 4. 단일모드또는연속모드 A/D 변환선택 ADCSRA 레지스터의 ADFR 설정 (0: 단일모드, 1: 연속모드 ) 5. A/D 변환을위한아날로그신호채널선택 ADMUX 레지스터의 MUX4~MUX0 설정 6. ADC 인터럽트활성화및전역인터럽트활성화 ADCSRA 레지스터의 ADIE 를세트 SREG 레지스터의 I 비트를세트. 즉, sei(); 7. ADC 인터럽트서비스루틴작성 8. A/D 변환시작 ADCSRA 레지스터의 ADSC 비트를세트
AD 변환회로예 12/28
납땜예 < 앞면 > < 뒷면 > 13/28
LCD 회로와 AD 변환회로결합 <ADC 연습을위해납땜후, LCD 회로와결합 > 14/28
AD 변환예제 1(1/4) ADC 인터럽트를이용하고, 키가눌리면단일모드로 AD 변환한결과를읽어와문자 LCD에출력 < 결과 > #include <avr/io.h> #include <avr/interrupt.h> #define SW PORTA0 #define PRESSED 0 #define RELEASED 1 ISR(ADC_vect) adc_result=adc; adc_rq=0; void ADC_init(void) ADCSRA = 1<<ADEN 1<<ADIE 0x06; ADCSRA &= ~(1<<ADFR); ADMUX=0x00; #define RS PORTE0 #define RW PORTE1 #define E PORTE2 volatile int adc_rq=0, adc_result=0; void gen_e_strobe(void) volatile int i; PORTE = 1<<E; for(i=0;i<10;i++); PORTE &= ~(1<<E); 15/28
16/28 AD 변환예제 1(2/4) void wait_busyflag(void) volatile int i; unsigned char bf; DDRD=0x00; PORTE=(PORTE & ~(1<<RS)) 1<<RW; do PORTE = 1<<E; for(i=0;i<10;i++); PORTE &= ~(1<<E); bf=pind & 1<<PORTD7; while (bf); void LCD_command(unsigned char data) wait_busyflag(); DDRD=0xff; PORTD=data; PORTE &= ~(1<<RS 1<<RW); gen_e_strobe(); void LCD_data_write(unsigned char data) wait_busyflag(); DDRD=0xff; PORTD=data; PORTE= (PORTE 1<<RS) & ~(1<<RW); gen_e_strobe();
17/28 AD 변환예제 1(3/4) void LCD_gotoxy(unsigned char X, unsigned char Y) int Tmp; switch(y) case 0: Tmp=0x80+X; break; case 1: Tmp=0xc0+X; break; default: Tmp=0x80+X; break; LCD_command(Tmp); void LCD_init(void) DDRE = 1<<RS 1<<RW 1<<E; PORTE &= ~(1<<RS 1<<E 1<<RW); LCD_command(0x38); LCD_command(0x01); LCD_command(0x06); LCD_command(0x0c);// 커서지우기 char *string[]=" ADC TEST ","ADC result= 0000"; int main(void) unsigned char r,c; unsigned char pre_sw=0x01, now_sw=0x01, ad_go=0; unsigned int num_1000,num_100,num_10,num_1;
18/28 AD 변환예제 1(4/4) ADC_init(); LCD_init(); DDRA &= ~(1<<SW); for(r=0;r<2;r++) for(c=0;c<17;c++) if(string[r][c]=='\0') LCD_gotoxy(0,1); break; else LCD_data_write(string[r][c]); sei(); while(1) if(ad_go) adc_rq=1; ADCSRA = 1<<ADSC; while(adc_rq); num_1000=0x30+(unsigned int)adc/1000; num_100=0x30+(unsigned int)(adc/100)%10; num_10=0x30+(unsigned int)(adc/10)%10; num_1=0x30+(unsigned int)adc%10; LCD_gotoxy(12,1); LCD_data_write(num_1000); LCD_data_write(num_100); LCD_data_write(num_10); LCD_data_write(num_1); ad_go=0; now_sw=pina; if(pre_sw==0x01) if(now_sw==0x00) ad_go=1; pre_sw=now_sw; return 0;
AD 변환예제 2(1/4) ADC 인터럽트를이용하고, 연속모드로 AD 변환한결과를읽어와문자 LCD에출력 ISR(ADC_vect) adc_result=adc; < 결과 > #include <avr/io.h> #include <avr/interrupt.h> void ADC_init(void) ADCSRA = 1<<ADEN 1<<ADIE 0x06; ADCSRA = 1<<ADFR; ADMUX=0x00; #define RS PORTE0 #define RW PORTE1 #define E PORTE2 volatile int adc_result=0; void gen_e_strobe(void) volatile int i; PORTE = 1<<E; for(i=0;i<10;i++); PORTE &= ~(1<<E); 19/28
20/28 AD 변환예제 2(2/4) void wait_busyflag(void) volatile int i; unsigned char bf; DDRD=0x00; PORTE=(PORTE & ~(1<<RS)) 1<<RW; do PORTE = 1<<E; for(i=0;i<10;i++); PORTE &= ~(1<<E); bf=pind & 1<<PORTD7; while (bf); void LCD_command(unsigned char data) wait_busyflag(); DDRD=0xff; PORTD=data; PORTE &= ~(1<<RS 1<<RW); gen_e_strobe(); void LCD_data_write(unsigned char data) wait_busyflag(); DDRD=0xff; PORTD=data; PORTE= (PORTE 1<<RS) & ~(1<<RW); gen_e_strobe();
21/28 AD 변환예제 2(3/4) void LCD_gotoxy(unsigned char X, unsigned char Y) int Tmp; switch(y) case 0: Tmp=0x80+X; break; case 1: Tmp=0xc0+X; break; default: Tmp=0x80+X; break; LCD_command(Tmp); void LCD_init(void) DDRE = 1<<RS 1<<RW 1<<E; PORTE &= ~(1<<RS 1<<E 1<<RW); LCD_command(0x38); LCD_command(0x01); LCD_command(0x06); LCD_command(0x0c);// 커서지우기 char *string[]=" ADC TEST ","ADC result= 0000"; int main(void) unsigned char r,c; unsigned int num_1000,num_100,num_10,num_1;
22/28 AD 변환예제 2(4/4) ADC_init(); LCD_init(); DDRA &= ~(1<<SW); for(r=0;r<2;r++) for(c=0;c<17;c++) if(string[r][c]=='\0') LCD_gotoxy(0,1); break; else LCD_data_write(string[r][c]); sei(); ADCSRA = 1<<ADSC; while(1) num_1000=0x30+(unsigned int)adc/1000; num_100=0x30+(unsigned int)(adc/100)%10; num_10=0x30+(unsigned int)(adc/10)%10; num_1=0x30+(unsigned int)adc%10; LCD_gotoxy(12,1); LCD_data_write(num_1000); LCD_data_write(num_100); LCD_data_write(num_10); LCD_data_write(num_1); return 0;
23/28 연습문제 1 아래와같이문자 LCD 에전압을 ADC 연속모드로측정하고결과를출력하시오 < 결과 > < 멀티미터측정결과 >
24/28 연습문제 2 아래와같이문자 LCD 에전압을 ADC 단일모드로측정하고결과를출력하시오 < 결과 > < 멀티미터측정결과 >
CdS 셀 1957 년네덜란드의필립스사와미국의 RCA 사가개발한황화카드뮴 (CdS, cadmiumsulfide) 의광전도성을이용한수광소자이다 황화카드뮴은강한빛이작용하면전기저항이줄고빛이약해지면전기저항이커지는성질을이용한수광소자이다 <CdS 셀의외형 > 25/28
CdS 셀추가회로 26/28
연습문제 3 아래와같이 CdS 셀에인가된전압을, ADC 인터럽트를이용하고연속모드로 AD 변환한결과를읽어와문자 LCD 에출력하시오 빛의세기에따른 AD 변환값의변화를관찰하시오 < 결과 > 27/28
질문?