7주차 AVR의 A/D 변환기제어레지스터및관련실습 Next-Generation Networks Lab.
3. 관련레지스터 표 9-4 레지스터 ADMUX ADCSRA ADCH ADCL 설명 ADC Multiplexer Selection Register ADC 의입력채널선택및기준전압선택외 ADC Control and Status Register A ADC 의동작을설정하거나동작상태를표시함 ADC Data Register High Byte ADC 의변환결과를저장하는레지스터중상위레지스터 ADC Data Register Low Byte ADC 의변환결과를저장하는레지스터중하위레지스터 58
ADMUX (ADC Multiplexer Selection Register) REFS1~REFS0 (Reference Selection) : 기준전압선택 ADLAR (ADC Left Adjust Result) : 데이터를왼쪽정렬로저장 MUX4~0 은 (analog MUX selection) A/D 변환할채널선택과단극성또 는차동입력방식을선택. 그림 9-16 - Default 설정의의미 - 기준전압은 AREF 전압으로설정 - 데이터는오른쪽정렬로저장 59
60 표 9-5
61
그림 9-18 ADCH ADCL ADCH ADCL 저해상도로사용할때유리함 8비트로사용하면 ADCH만읽음 62
ADCSRA (ADC Control and Status Register A) ADEN (ADC Enable) : ADC 동작 그림 9-17 ADSC (ADC Start Conversion) : ADC 변환시작. 변환완료후에 0 로됨 ADFR (ADC Free Running) : Free-running mode 로설정 ADIF (ADC Interrupt Flag) : ADC 가완료되면 1 로세트되면서인터럽트 를요청. 인터럽트가서비스되면하드웨어적으로 0 으로설정됨 ADIE (ADC Interrupt Enable) : ADC 인터럽트서비스를개별적으로허용 ADPS2~0 (ADC Prescaler Select) : ADC 변환클럭을위한분주비설정 63
ADCH / ADCL (ADC Data Register High byte, Low byte) ADC 결과값인 10 비트를저장하는 2 개의 8 비트레지스터 항상 ADCL 을먼저읽고후에 ADCH 를읽을것! ADC 데이터변환결과 단극성입력채널을사용하는경우의변환결과 차동입력채널을사용하는경우의변환결과 64
ADC 설정사항 ADMUX 레지스터 기준전압 : 입력신호의최고전압 신호입력채널 변환된데이터의정렬 : 처리방식 (8비트, 10비트 ) ADCSRA 레지스터 Free-running 여부 변환클럭속도 : Prescaler 설정 인터럽트활용여부 65
ADC 초기화함수 void adc_init (INT8 channel) asm("cli"); CLI); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0); // 기준전압 ADMUX = (0<<ADLAR); // 10비트해상도 ADMUX = channel; ADCSRA= (1<<ADEN) (1<<ADSC) (1<<ADFR) (1<<ADIE) (0<<ADPS2) (1<<ADPS1) (1<<ADPS0); // 기준클럭 : 1MHz/ 8 asm("sei"); // sei( ); //SREG = 0x80; 비트설정동작비트설정동작 REF1:0 00 AREF input ADSC 1 변환시작 ADLAR 0 우측정렬 ADFR 1 Free-running MUX4:0 channel 입력선택 ADIE 1 Interrupt 허용 ADEN 1 Enable ADPS2:0 011 Prescaler 8 분주 66
예제 9.1 온도센서 TMP35 온도센서를활용하여현재온도를측정한다. TMP35 의출력전압을 ADC 의채널 #0 을통해 A/D 변환한다. A/D 변환된 10 비트값으로부터 TMP35 출력전압과온도를계산한다. CPU 클럭주파수 : 1MHz 내부발진기 기준전압 : 외부 AREF 입력전압 입력채널 : ch #0 해상도 : 10비트 온도를 PORTA 의 7-segment 에출력한다. 예를들어, 현재온도가 28 도이면, 2 개의 7-segment 에 28 을출력한다. 67
Port A CPU Board 7-segment (Decoder) 온도센서 (TMP35) Port F0 68
온도센서 (TMP35) 및구동회로도 회로도 1 3 2 1 2 3 69
Features Calibrated directly in Celsius (Centigrade) Linear +10.0 0 mv/c scale factor 0.5C accuracy guaranteeable (at +25 C) Rated for full -55 to +150C range Suitable for remote applications Low cost due to wafer-level l trimming i Operates from 4 to 30 volts 70
Temperature vs. Output Voltage 71
예제 9-1 ADC ( 온도센서 TMP35) typedef unsigned char INT8; typedef unsigned int INT16; #define F_CPU 1000000UL #include <avr/io.h> #include <util/delay.h> l #include <avr/interrupt.h> #define ADC_CH CH 0 // 입력채널 #define TMP35 100 // TMP35 환산 //#define REF_VOLTAGE 2.56 // 기준전압 //#define REF_VOLTAGE 3.33 // 기준전압 #define REF_VOLTAGE 5.0 // 기준전압 //#define RESOLUTION 256.0 // 8비트 #define RESOLUTION 1024.00 // 10 비트 volatile INT16 read_adc = 0; volatile INT8 adc_flag = 0; ISR(ADC_vect) // ADC interrupt function read_adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(int8 channel) asm("cli"); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0); // 기준전압 ADMUX = (0<<ADLAR); // 10비트해상도 ADMUX = channel; // ADMUX = 0b0000000; ADCSRA = (1<<ADEN) (1<<ADSC) (1<<ADFR) (1<<ADIE) (0<<ADPS2) (1<<ADPS1) (1<<ADPS0); 1 // 기준클럭 : 1MHz / 8 // ADCSRA = 0b11101011; asm("sei"); // sei( ); //SREG = 0x80; 72
예제 9-1 ADC ( 온도센서 TMP35) int main (void) INT8 count=0; INT8 Value_10, Value_01; volatile float temp_volt = 0.0; volatile float Temperature = 0.0; DDRG = 0xFF; DDRA = 0xFF; adc_init(adc_ch); CH); // Ch # of ADC _delay_ms(10); if(adc_flag == 1) PORTG = count++; // adc_flag를 clear adc_flag = 0; // 10 비트 ADC 값으로부터전압계산 temp_volt = read_adc * (REF_VOLTAGE/RESOLUTION); // 계산된전압에서온도계산 Temperature = temp_volt * (float)tmp35; PORTA = 0x99; _delay_ms(500); while(1) // 우측프로그램추가 return 0; // 온도값을 7-segment에표현 Value_10 = Temperature / 10; Value_01 = (INT8) Temperature % 10; PORTA = (Value_10<<4) Value_01; _delay_ms(200); 73
예제 9-2 ADC ( 온도센서 온도센서 TMP35 입력채널, 기준전압설정변경 ) TMP35 온도센서를활용하여현재온도를측정한다. TMP35 의출력전압을 ADC 의채널 #2 를통해 A/D 변환한다. A/D 변환된 10 비트값으로부터 TMP35 출력전압과온도를계산한다. CPU 클럭주파수 : 1MHz 내부발진기 기준전압 : 내부 2.56V 입력채널 : ch #2 해상도 : 10비트 온도를 PORTA 의 7-segment 에출력한다. 예를들어, 현재온도가 28 도이면, 2 개의 7-segment 에 28 을출력한다. 74
예제 9-2 typedef unsigned char INT8; typedef unsigned int INT16; #define F_CPU 1000000UL #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define ADC_CH 2 // 입력채널 #define TMP35 100 // TMP35 환산 #define REF_VOLTAGE 2.56 // 기준전압 //#define REF_VOLTAGE 3.3 // 기준전압 //#define REF_VOLTAGE 5.0 // 기준전압 //#define RESOLUTION 256.0 // 8비트 #define RESOLUTION 1024.00 // 10 비트 volatile INT16 read_adc = 0; volatile INT8 adc_flag = 0; ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(int8 channel) asm("cli"); CLI); // cli( ); ADMUX= (1<<REFS1) (1<<REFS0); // 기준전압 ADMUX = (0<<ADLAR); // 10비트해상도 ADMUX = channel; ADCSRA= (1<<ADEN) (1<<ADSC) (1<<ADFR) (1<<ADIE) (0<<ADPS2) (1<<ADPS1) (1<<ADPS0); // 기준클럭 : 1MHz / 8 asm("sei"); // sei( (); //SREG = 0x80; 75
예제 9-2 int main (void) INT8 count=0; INT8 Value_10, Value_01; volatile float temp_volt = 0.0; volatile float Temperature = 0.0; DDRG = 0xFF; DDRA = 0xFF; adc_init(adc_ch); CH); // Ch # of ADC _delay_ms(10); if(adc_flag == 1) PORTG = count++; // adc_flag를 clear adc_flag = 0; // 10 비트 ADC 값으로부터전압계산 temp_volt = read_adc * (REF_VOLTAGE/RESOLUTION); // 계산된전압에서온도계산 Temperature = temp_volt * (float)tmp35; PORTA = 0x99; _delay_ms(500); while(1) // 우측프로그램추가 return 0; // 온도값을 7-segment에표현 Value_10 = Temperature / 10; Value_01 = (INT8) Temperature % 10; PORTA = (Value_10<<4) Value_01; _delay_ms(200); 76
예제 9-3 ADC ( 온도센서 온도센서 TMP35 클럭속도설정변경 ) TMP35 온도센서를활용하여현재온도를측정한다. TMP35 의출력전압을 ADC 의채널 #2 를통해 A/D 변환한다. A/D 변환된 10 비트값으로부터 TMP35 출력전압과온도를계산한다. CPU 클럭주파수 : 4MHz 내부발진기 기준전압 : 외부 AREF 입력전압 입력채널 : ch #2 해상도 : 10비트 Prescaler 설정을 000에서 111까지변화하면서결과확인 온도를 PORTA 의 7-segment 에출력한다. 예를들어, 현재온도가 28 도이면, 2 개의 7-segment 에 28 을출력한다. 77
예제 9-3 typedef unsigned char INT8; typedef unsigned int INT16; #define F_CPU 4000000UL #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define ADC_CH 2 // 입력채널 #define TMP35 100 // TMP35 환산 //#define REF_VOLTAGE 2.56 // 기준전압 //#define REF_VOLTAGE 3.3 // 기준전압 #define REF_VOLTAGE 5.0 // 기준전압 //#define RESOLUTION 256.0 // 8비트 #define RESOLUTION 1024.00 // 10 비트 volatile INT16 read_adc = 0; volatile INT8 adc_flag = 0; ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(int8 channel) asm("cli"); CLI); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0); // 기준전압 ADMUX = (0<<ADLAR); // 10비트해상도 ADMUX = channel; ADCSRA= (1<<ADEN) (1<<ADSC) (1<<ADFR) (1<<ADIE) (0<<ADPS2) (0<<ADPS1) (1<<ADPS0); // 기준클럭 : 1MHz / 8 asm("sei"); // sei( (); //SREG = 0x80; 78
예제 9-3 int main (void) INT8 count=0; INT8 Value_10, Value_01; volatile float temp_volt = 0.0; volatile float Temperature = 0.0; DDRG = 0xFF; DDRA = 0xFF; adc_init(adc_ch); CH); // Ch # of ADC _delay_ms(10); if(adc_flag == 1) PORTG = count++; // adc_flag를 clear adc_flag = 0; // 10 비트 ADC 값으로부터전압계산 temp_volt = read_adc * (REF_VOLTAGE/RESOLUTION); // 계산된전압에서온도계산 Temperature = temp_volt * (float)tmp35; PORTA = 0x99; _delay_ms(500); while(1) // 우측프로그램추가 return 0; // 온도값을 7-segment에표현 Value_10 = Temperature / 10; Value_01 = (INT8) Temperature % 10; PORTA = (Value_10<<4) Value_01; _delay_ms(200); 79
예제 9-4 ADC ( 온도센서 온도센서 TMP35 Free-running running 해제 ) TMP35 온도센서를활용하여현재온도를측정한다. TMP35 의출력전압을 ADC 의채널 #2 를통해 A/D 변환한다. A/D 변환된 10 비트값으로부터 TMP35 출력전압과온도를계산한다. CPU 클럭주파수 : 1MHz 내부발진기 기준전압 : 외부 AREF 입력전압 입력채널 : ch #2 해상도 : 10비트 Free-running을해제하고결과확인 주기적으로 A/D 변환을하기위한명령은?? 온도를 PORTA 의 7-segment 에출력한다. 예를들어, 현재온도가 28 도이면, 2 개의 7-segment 에 28 을출력한다. 80
예제 9-4 typedef unsigned char INT8; typedef unsigned int INT16; #define F_CPU 1000000UL #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define ADC_CH 2 // 입력채널 #define TMP35 100 // TMP35 환산 //#define REF_VOLTAGE 2.56 // 기준전압 //#define REF_VOLTAGE 3.3 // 기준전압 #define REF_VOLTAGE 5.0 // 기준전압 //#define RESOLUTION 256.0 // 8비트 #define RESOLUTION 1024.00 // 10 비트 volatile INT16 read_adc = 0; volatile INT8 adc_flag = 0; ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(int8 channel) asm("cli"); CLI); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0); // 기준전압 ADMUX = (0<<ADLAR); // 10비트해상도 ADMUX = channel; ADCSRA= (1<<ADEN) (1<<ADSC) (0<<ADFR) (1<<ADIE) (0<<ADPS2) (1<<ADPS1) (1<<ADPS0); // 기준클럭 : 1MHz / 8 asm("sei"); // sei( (); //SREG = 0x80; 81
예제 9-4 int main (void) INT8 count=0; INT8 Value_10, Value_01; volatile float temp_volt = 0.0; volatile float Temperature = 0.0; DDRG = 0xFF; DDRA = 0xFF; adc_init(adc_ch); CH); // Ch # of ADC _delay_ms(10); if(adc_flag == 1) PORTG = count++; // adc_flag를 clear adc_flag = 0; // 10 비트 ADC 값으로부터전압계산 temp_volt = read_adc * (REF_VOLTAGE/RESOLUTION); // 계산된전압에서온도계산 Temperature = temp_volt * (float)tmp35; PORTA = 0x99; _delay_ms(500); while(1) // 우측프로그램추가 return 0; // 온도값을 7-segment에표현 Value_10 = Temperature / 10; Value_01 = (INT8) Temperature % 10; PORTA = (Value_10<<4) Value_01; _delay_ms(200); ADCSRA = (1<<ADSC); // ADCSRA = 0x40; 82