8주차중간고사 ( 인터럽트및 A/D 변환기문제및풀이 ) Next-Generation Networks Lab.
외부입력인터럽트예제 문제 1 포트 A 의 7-segment 에초시계를구현한다. Tact 스위치 SW3 을 CPU 보드의 PE4 에연결한다. 그리고, SW3 을누르면하강 에지에서초시계가 00 으로초기화된다. 동시에 Tact 스위치 SW4 를 CPU 보드의 PD1 에연결한다. 그리고, SW4 를누르 면상승에지의수를카운트하여포트 C 의 7-segment 에표시한다. 위의기능들을외부입력인터럽트를활용하여동시에구현한다. 84
Port C 7-segment (Direct) CPU Board Port A 7-segment (Decoder) Tact Switch Port E4 Port D1 85
문제 1 제어프로그램 typedef unsigned char INT8; DDRD = 0x00; // Tact SW typedef unsigned int INT16; DDRE = 0x00; // Tact SW #define F_CPU 1000000UL EICRA = 0x0C; // INT1 rising EICRB = 0x02; // INT4 falling #include <avr/io.h> EIMSK = 0x12; // INT1, INT4 enable #include <util/delay.h> EIFR = 0x00; // Flag clear #include <avr/interrupt.h> INT8 i, j, k=0 ; SREG = 0x80; //sei(); while(1) for(i=0; i<6; i++) ISR(INT4_vect) // INT4 interrupt function i=0; ;j j=0; ; for(j=0; j<10; j++) ISR(INT1_vect) // INT1 interrupt function PORTA = (i << 4) j; PORTC = FND[k++] ; _delay_ms(1000); int main (void) DDRA = 0xFF; // 7-segment DDRC = 0xFF; // 7-segment return 0; 86
문제 2 A/D 변환기 ( 온도센서 TMP35 8 비트해상도 ) TMP35 온도센서를활용하여현재온도를측정한다. TMP35 의출력전압을 ADC 의채널 #2 를통해 A/D 변환한다. A/D 변환된 8 비트값으로부터 TMP35 출력전압과온도를계산한다. CPU 클럭주파수 : 1MHz 내부발진기 기준전압 : AVCC 입력전압 입력채널 : ch #2 해상도 : 8비트 온도를 PORTA 의 7-segment 에출력한다. 예를들어, 현재온도가 28 도이면, 2 개의 7-segment 에 28 을출력한다. 87
Port A CPU Board 7-segment (Decoder) 온도센서 (TMP35) Port F2 88
문제 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 INT8 read_adc = 0; volatile INT8 adc_flag = 0; ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCH; adc_flag = 1; void adc_init(int8 channel) asm("cli"); // cli( ); ADMUX= (0<<REFS1) (1<<REFS0); REFS0) // 기준전압 ADMUX = (1<<ADLAR); // 8비트해상도 ADMUX = channel; ADCSRA= (1<<ADEN) (1<<ADSC) (1<<ADFR) (1<<ADIE) (0<<ADPS2) (1<<ADPS1) (1<<ADPS0); // 기준클럭 : 1MHz / 8 asm("sei"); // sei( ); //SREG = 0x80; 89
문제 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(2000); while(1) // 우측프로그램추가 return 0; // 온도값을 7-segment에표현 Value_10 = Temperature / 10; Value_01 = (INT8) Temperature % 10; PORTA = (Value_10<<4) Value_01; _delay_ms(200); 90
A/D 변환기 가변저항의전압과저항값표시 가변저항에서분배된전압을 ADC 의채널 #1 을통해 A/D 변환한다. A/D 변환된 10 비트값으로부터분배된전압과저항값을계산한다. 문제 3 10 비트값을 16 진수로 3 개의 7-segment (PORTC, PORTA) 에출력한다. 문제 4 계산된전압을 3 개의 7-segment (PORTC, PORTA) 에출력한다. 예를들어, 문제 5 2.74V 이면 2 를 PORTC 에출력하고, 74 를 PORTA 에출력한다. 계산된저항값을 k 단위로 3 개의 7-segment (PORTC, PORTA) 에출력한다. 예 를들어, 5.48k 이면 5 를 PORTC 에출력하고, 48 를 PORTA 에출력한다. 91
Port C 7-segment (Direct) CPU Board Port A 7-segment (Decoder) 가변저항 Port F1 92
+5V x : 10-bit ADC 의출력값 y : ADC 의입력전압 z : 가변저항의저항값 4k ADC0 6k 93
정수와실수를 10 진수로 3 개의 7-segment 에출력 typedef unsigned char INT8; typedef unsigned int INT16; #define F_CPU 1000000UL #include <avr/io.h> INT8 FND[ ] = 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xD8, 0x80, 0x90; int main(void) float Float_num; INT16 Int_num, Int_temp; INT8 Val_100, Val_10, Val_01; Float_num = 3.74 ; Int_num = 512; // 3자리정수를 7-segment에표현 Val_100 = Int_num / 100; Int_temp temp = (Int_num num (Val_100 * 100)); Val_10 = Int_temp / 10; Val_01 = Int_temp % 10; PORTC = FND[Val_100]; PORTA = (Val_10 << 4) Val_01; _delay_ms(2000); // 0에서 10 사이의실수를 7-segment에표현 Int_temp = Float_num * 100; Int_temp = (Int_temp (Val_100 * 100)); Val_10 = Int_temp / 10; Val_01 = Int_temp % 10; PORTC = FND[Val_100]; PORTA = (Val_10 << 4) Val_01; _delay_ms(2000); 94
문제 3 제어프로그램 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 T_RES 10 // VR 의전체저항값 ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(unsigned char channel) asm("cli"); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0) (0<<ADLAR); volatile INT16 read_adc = 0; ADMUX = channel; volatile INT8 adc_flag = 0; ADCSRA= (1<<ADEN) (1<<ADSC) INT8 FND[ ] = 0xC0, 0xF9, 0xA4, 0xB0, (1<<ADFR) (1<<ADIE) 0990920820 0x99, 0x92, 0x82, 0xD8, 0x80, 0x90; (1<<ADPS2) (1<<ADPS1) (1<<ADPS0); asm("sei"); // sei( ); //SREG = 0x80; 95
문제 3 제어프로그램 int main (void) INT16 Int_ temp, count=0; INT8 Val_100, Val_10, Val_01; volatile float temp_volt = 0.0; volatile float Resistance = 0.0; DDRG = 0xFF; DDRA = 0xFF; DRC = 0xFF; adc_init(1); // Channel # of ADC _delay_ms(10); if(adc_flag == 1) PORTG = count++; // adc_flag를 clear adc_flag = 0; // 10비트 ADC 값으로부터전압계산 temp_volt = read_adc * (5.0/1023.0); // 계산된전압에서저항값계산 Resistance = temp_volt / 5.0 * T_RES; PORTC = FND[1]; PORTA = 0x23; // 10비트 A/D 변환값을 10진수로표현 _delay_ms(2000); Val_100 = read_adc d / 100; while(1) Int_temp = (read_adc (Val_100 * 100)); Val_10 = Int_temp / 10; // 우측프로그램추가 Val_01 = Int_temp temp %10 10; PORTC = FND[Val_100]; return 0; PORTA = (Val_10 << 4) Val_01; _delay_ms(2000); 96
문제 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 T_RES 10 // VR 의전체저항값 ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(unsigned char channel) asm("cli"); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0) (0<<ADLAR); volatile INT16 read_adc = 0; ADMUX = channel; volatile INT8 adc_flag = 0; ADCSRA= (1<<ADEN) (1<<ADSC) INT8 FND[ ] = 0xC0, 0xF9, 0xA4, 0xB0, (1<<ADFR) (1<<ADIE) 0990920820 0x99, 0x92, 0x82, 0xD8, 0x80, 0x90; (1<<ADPS2) (1<<ADPS1) (1<<ADPS0); asm("sei"); // sei( ); //SREG = 0x80; 97
문제 4 제어프로그램 if(adc_flag == 1) PORTG = count++; // adc_flag 를 clear adc_flag = 0; // 10 비트 ADC 값으로부터전압계산 temp_volt = read_adc * (5.0/1023.0); // 계산된전압에서저항값계산 Resistance = temp_volt / 5.0 * T_RES; // 전압값을소수점 2자리로표현 Int_temp t = temp_volt * 100; Int_temp = (Int_temp (Val_100 * 100)); Val_10 = Int_temp / 10; Val_01 = Int_temp temp % 10; PORTC = FND[Val_100]; PORTA = (Val_10 << 4) Val_01; _delay_ms(2000); 98
문제 5 제어프로그램 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 T_RES 10 // VR 의전체저항값 ISR(ADC_vect) // ADC interrupt function read_adc adc = ADCL; read_adc += (ADCH<<8); adc_flag = 1; void adc_init(unsigned char channel) asm("cli"); // cli( ); ADMUX= (0<<REFS1) (0<<REFS0) (0<<ADLAR); volatile INT16 read_adc = 0; ADMUX = channel; volatile INT8 adc_flag = 0; ADCSRA= (1<<ADEN) (1<<ADSC) INT8 FND[ ] = 0xC0, 0xF9, 0xA4, 0xB0, (1<<ADFR) (1<<ADIE) 0990920820 0x99, 0x92, 0x82, 0xD8, 0x80, 0x90; (1<<ADPS2) (1<<ADPS1) (1<<ADPS0); asm("sei"); // sei( ); //SREG = 0x80; 99
문제 5 제어프로그램 if(adc_flag == 1) PORTG = count++; // adc_flag 를 clear adc_flag = 0; // 10 비트 ADC 값으로부터전압계산 temp_volt = read_adc * (5.0/1023.0); // 계산된전압에서저항값계산 Resistance = temp_volt / 5.0 * T_RES; // k옴단위의저항값을소수점 2자리로표현 Int_temp t = Resistance * 100; Int_temp = (Int_temp (Val_100 * 100)); Val_10 = Int_temp / 10; Val_01 = Int_temp temp % 10; PORTC = FND[Val_100]; PORTA = (Val_10 << 4) Val_01; _delay_ms(2000); 100