ATmega128 외부인터럽트실습 Prof. Jae Young Choi ( 최재영교수 ) (2015 Spring) Prof. Jae Young Choi
외부인터럽트실험 외부인터럽트를사용하기위해관렦레지스터를설정 일반적으로 I/O 포트에대한설정이끝난후에외부인터럽트나타이머 / 카운터설정 PE4~7 번까지 4 개의외부인터럽트 INT4~INT7 까지사용
외부인터럽트사용법요약 사용하고자하는외부인터럽트인에이블비트셋 사용레지스터 : EMISK 트리거방식설정 ( 하강에지 / 상승에지 / 레벨트리거중선택 ) 사용레지스터 : EICRA(INT0~INT3, EICRB(INT4~INT7) 전역인터럽트인에이블비트 I 셋 사용레지스터 : SREG( 최상위비트 ) 가능하면모든초기설정이끝난후제일마지막에 I 비트를셋 인터럽트함수작성
( 예제 4-1) 외부인터럽트 4 에의한 LED 점멸실험 ( 하강에지 ) KUT-128_COM 보드의 SW1/INT4 이눌려질때마다외부인터럽트 4 가발생하여 LED 가순차적으로점멸하도록프로그램을작성하라. 외부인터럽트 4 의입력트리거는하강에지에서발생하도록한다.
( 예제 4-1) 외부인터럽트 4 에의한 LED 점멸실험 ( 하강에지 ) // ex4-1.c // 외부인터럽트 4 에대한 LED 순차점멸실험 ( 하강에지 ) #include <mega128.h> unsigned char led = 0xFE; void main(void) // 포트초기화 DDRC = 0xFF; // 포트 C 출력설정 DDRE = 0b00000010; // 포트 E 입력 (PE1 출력 ) // 외부인터럽트 4 서비스루틴 interrupt [EXT_INT4] void external_int4(void) led = led << 1; // 1 비트쉬프트 led = led 0b00000001; // 최하위비트셋 if(led == 0xFF) led = 0xFE; // 모두 off 상태면초기값재설정 PORTC = led; // 포트출력 PORTC = led; // 포트 C 에초기값출력 // 인터럽트초기화 EIMSK = 0b00010000; EICRB = 0b00000010; SREG = 0x80; // 외부인터럽트4 인에이블 // 외부인터럽트4 : 하강에지 // 전역인터럽트인에이블비트셋 while(1);
( 예제 4-2) 외부인터럽트 4 에의한 LED 점멸실험 ( 상승에지 ) KUT-128_COM 보드의 SW1/INT4 이눌렸다떼어지는순간 ( 상승에지 ) 외부인터럽트 4 가발생하여 LED 가순차적으로점멸되도록프로그램을작성하라.
( 예제 4-2) 외부인터럽트 4 에의한 LED 점멸실험 ( 상승에지 ) // ex4-2.c // 외부인터럽트 4 에대한 LED 순차점멸실험 ( 상승에지 ) #include <mega128.h> unsigned char led = 0xFE; void main(void) // 포트초기화 DDRC = 0xFF; // 포트 C 출력설정 DDRE = 0b00000010; // 포트 E 입력 (PE1 출력 ) // 외부인터럽트 4 서비스루틴 interrupt [EXT_INT4] void external_int4(void) led = led << 1; // 1 비트쉬프트 led = led 0b00000001; // 최하위비트셋 if(led == 0xFF) led = 0xFE; // 모두 off 상태면초기값재설정 PORTC = led; // 포트출력 PORTC = led; // 인터럽트초기화 EIMSK = 0b00010000; EICRB = 0b00000011; 지 SREG = 0x80; 트셋 // 포트 C 에초기값출력 // 외부인터럽트4 인에이블 // 외부인터럽트4 : 상승에 // 전역인터럽트인에이블비 while(1);
( 예제 4-3) 외부인터럽트 4 에의한 LED 전자룰렛실험 [ 레벨트리거 ] 외부인터럽트 4 에대한실험으로입력트리거방식을레벨트리거방식으로하여 SW1 이눌려지고있는동안 LED 가순차점멸하도록하고, SW1 에서손을떼면순차점멸하던 LED 가정지하도록프로그램을작성하라.
( 예제 4-3) 외부인터럽트 4 에의한 LED 전자룰렛실험 [ 레벨트리거 ] // ex4-3.c // 외부인터럽트 4 에의한 LED 전자룰렛실험 ( 레벨트리거 ) #include <mega128.h> #include <delay.h> unsigned char led = 0xFE; // 외부인터럽트4 서비스루틴 interrupt [EXT_INT4] void external_int4(void) // LED 순차점멸 led = led << 1; // 1비트쉬프트 led = led 0b00000001; // 최하위비트셋 if(led == 0xFF) led = 0xFE; // 모두 off 상태면초기값재설정 PORTC = led; // 포트출력 void main(void) // 포트초기화 DDRC = 0xFF; // 포트 C 출력설정 DDRE = 0b00000010; // 포트 E 입력설정 (PE1 출력 ) PORTC = led; // 포트 C 에초기값출력 // 인터럽트초기화 EIMSK = 0b00010000; // 외부인터럽트4 인에이블 EICRB = 0b00000000; // 외부인터럽트4 : low 레벨 SREG = 0x80; // 전역인터럽트인에이블비트셋 while(1); // 무한루프
( 예제 4-4) 외부인터럽트 4 에의한스위치입력실험 외부인터럽트 4 를이용하여 SW1/INT4 를누를때마다맨우측 7-Segment 의표시값이 0 1 2 3 9 0 1.. 이표시되도록프로그램을작성하라.
( 예제 4-4) 외부인터럽트 4 에의한스위치입력실험 // ex4-4.c #include <mega128.h> #include <delay.h> flash char seg_pat[16]= 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f; unsigned char N1 = 0; while(1) PORTD = ((seg_pat[n1] & 0x0F) << 4) (PORTD & 0x0F); // A, B, C, D 표시 PORTB = (seg_pat[n1] & 0x70 ) (PORTB & 0x0F); // E, F, G 표시 void main(void) DDRB = 0xF0; DDRD = 0xF0; DDRG = 0x0F; // 인터럽트초기화 EIMSK = 0b00010000; EICRB = 0b00000010; SREG = 0x80; PORTG = 0b00001000; ON(PG3=1) // 포트 B 상위 4비트출력설정 // 포트 D 상위 4비트출력설정 // 포트 G 하위 4비트출력설정 // 외부인터럽트4 인에이블 // 외부인터럽트4 : 하강에지 // 전역인터럽트인에이블비트셋 // 맨우측 7-Segment DIG4 // 외부인터럽트 4 서비스루틴 interrupt [EXT_INT4] void external_int4(void) N1 = (N1 + 1) % 10; // 값 +1
( 예제 4-5) 두개의외부인터럽트를이용한 10 진네자리입력실험 두개의스위치 SW1/INT4 와 SW2/INT5 맊을이용하여네자리를입력하는프로그램을작성하라. 여기서, SW2 는입력될자리 ( 위치 ) 를나타내고, SW1 눌려지면현재선택된자리의값을 +1 하도록한다. SW2 가눌려지면입력될위치를 1 자리 10 자리 100 자리 1000 자리 1 자리 10 자리.. 로이동하도록한다.
( 예제 4-5) 두개의외부인터럽트를이용한 10 진네자리입력실험 // ex4-5.c // 두개의스위치를이용한네자리입력실험 #include <mega128.h> #include <delay.h> typedef unsigned char u_char; flash u_char seg_pat[10]= 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,0x7f, 0x6f; u_char N1 = 0, N10 = 0, N100 = 0, N1000 = 0; u_char pos = 0; // 0 : 1자리, 1 : 10자리, 2 : 100자리, 3 : 1000자리 void Seg4_out(void); void main(void) DDRB = 0xF0; DDRD = 0xF0; DDRG = 0x0F; // 인터럽트초기화 EIMSK = 0b00110000; EICRB = 0b00001010; SREG = 0x80; while(1) Seg4_out(); // 네자리수 7-Segment 출력 // 포트 B 상위 4비트출력설정 // 포트 D 상위 4비트출력설정 // 포트 G 하위 4비트출력설정 // 외부인터럽트 4,5 인에이블 // 외부인터럽트 4,5 : 하강에지 // 전역인터럽트인에이블비트셋 // 네자리수 7-Segment 출력함수 void Seg4_out(void) PORTG = 0b00001000; // 7-Seg DIG4 ON(PG3=1), 1자리표시 PORTD = ((seg_pat[n1] & 0x0F) << 4) (PORTD & 0x0F); // A, B, C, D 표시 PORTB = (seg_pat[n1] & 0x70 ) (PORTB & 0x0F); // E, F, G 표시 PORTG = 0b00000100; // 7-Seg DIG3 ON(PG2=1), 10자리표시 PORTD = ((seg_pat[n10] & 0x0F) << 4) (PORTD & 0x0F); // A, B, C, D 표시 PORTB = (seg_pat[n10] & 0x70 ) (PORTB & 0x0F); // E, F, G 표시 PORTG = 0b00000010; // 7-Seg DIG2 ON(PG1=1), 100자리표시 PORTD = ((seg_pat[n100] & 0x0F) << 4) (PORTD & 0x0F); // A, B, C, D 표시 PORTB = (seg_pat[n100] & 0x70 ) (PORTB & 0x0F); // E, F, G 표시 PORTG = 0b00000001; // 7-Seg DIG1 ON(PG0=1), 1000자리표시 PORTD = ((seg_pat[n1000] & 0x0F) << 4) (PORTD & 0x0F); // A, B, C, D 표시 PORTB = (seg_pat[n1000] & 0x70 ) (PORTB & 0x0F); // E, F, G 표시 // 외부인터럽트 4 서비스루틴 interrupt [EXT_INT4] void external_int4(void) if(pos == 0) N1 = (N1 + 1) % 10; // 1 자리 +1 else if(pos == 1) N10 = (N10 + 1) % 10; // 10 자리 +1 else if(pos == 2) N100 = (N100 + 1) % 10; // 100 자리 +1 else N1000 = (N1000 + 1) % 10; // 1000 자리 +1 // 외부인터럽트5 서비스루틴 interrupt [EXT_INT5] void external_int5(void) pos = (pos + 1) % 4; // 입력자리이동
( 예제 4-6) 외부인터럽트를이용한간이시계제작 delay_ms() 함수를이용하여시간과분을 7-Segment 에출력하는프로그램을작성하라. 시간과분의조정은 [ 예제 4-5] 와같이두 개의스위치를이용하여입력하도록한다.
( 예제 4-6) 외부인터럽트를이용한간이시계제작 // ex4-6.c // 외부인터럽트를이용한간이시계제작 #include <mega128.h> #include <delay.h> typedef unsigned char u_char; flash u_char seg_pat[10]= 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f; u_char N1, N10, N100, N1000; u_char pos = 0; // 0 : 1자리, 1 : 10자리, 2 : 100자리, 3 : 1000자리 u_char hour = 12, min = 0, sec = 0; void Time_out(void); void main(void) char i; DDRB = 0xF0; DDRD = 0xF0; DDRG = 0x0F; // 인터럽트초기화 EIMSK = 0b00110000; EICRB = 0b00001010; SREG = 0x80; // 시간표시함수 // 포트 B 상위 4비트출력설정 // 포트 D 상위 4비트출력설정 // 포트 G 하위 4비트출력설정 // 외부인터럽트 4,5 인에이블 // 외부인터럽트 4,5 : 하강에지 // 전역인터럽트인에이블비트셋 while(1) for(i = 0;i < 49;i++) Time_out(); // 약 1 초간반복표시 sec = sec + 1; // 초값 +1 if(sec == 60) sec = 0; min = min + 1; // 분값 +1 if(min == 60) min = 0; hour = (hour + 1) % 24; // 시간 +1 // 시간표시함수 void Time_out(void) PORTG = 0b00001000; // 7-Seg DIG4 ON(PG3=1), 분 1자리표시 PORTD = ((seg_pat[min % 10] & 0x0F) << 4) (PORTD & 0x0F); PORTB = (seg_pat[min % 10] & 0x70 ) (PORTB & 0x0F); PORTG = 0b00000100; // 7-Seg DIG3 ON(PG2=1), 분 10자리표시 PORTD = ((seg_pat[min / 10] & 0x0F) << 4) (PORTD & 0x0F); PORTB = (seg_pat[min / 10] & 0x70 ) (PORTB & 0x0F); PORTG = 0b00000010; // 7-Seg DIG2 ON(PG1=1), 시간 1자리표시 PORTD = ((seg_pat[hour % 10] & 0x0F) << 4) (PORTD & 0x0F); PORTB = (seg_pat[hour % 10] & 0x70 ) (PORTB & 0x0F); PORTG = 0b00000001; // 7-Seg DIG1 ON(PG0=1), 시간 10자리표시 PORTD = ((seg_pat[hour / 10] & 0x0F) << 4) (PORTD & 0x0F); PORTB = (seg_pat[hour / 10] & 0x70 ) (PORTB & 0x0F);
( 예제 4-6) 외부인터럽트를이용한간이시계제작 ( 계속 ) // 외부인터럽트요구 4 서비스루틴 interrupt [EXT_INT4] void external_int4(void) N1 = min % 10; // 현재분 1자리추출 N10 = min / 10; // 현재분 10자리추출 N100 = hour % 10; // 현재시간 1자리추출 N1000 = hour / 10; // 현재시간 10자리추출 if(pos == 0) N1 = (N1 + 1) % 10; // 분 1 단위 +1 else if(pos == 1) N10 = (N10 + 1) % 6; // 분 10 단위 +1 else if(pos == 2) // 시간 1 단위 +1 if(n1000 == 2) N100 = (N100 + 1) % 4; else N100 = (N100 + 1) % 10; else // 시간 10 단위 +1 if(n100 < 4) N1000 = (N1000 + 1) % 3; else if(n1000!= 1) N1000 = (N1000 + 1) % 3; hour = N1000 * 10 + N100; min = N10 * 10 + N1; // 시간계산 // 분계산 // 외부인터럽트요구 5 서비스루틴 interrupt [EXT_INT5] void external_int5(void) pos = (pos + 1) % 4; // 입력자리이동