7 장. 인터럽트의동작 한국산업기술대학교 이응혁교수 WWW.ROBOTICSLAB.CO.KR 1
7.1 인터럽트 (Interrupt) 개요 인터럽트개념 프로그램이수행되고있는동안에어떤조건이발생하여수행중인프로그램을일시적으로중지시키게만드는조건이나사건의발생 비동기적으로처리 다른프로그램이수행되는동안여러개의사건을처리할수있는메커니즘 인터럽트가발생하면마이크로컨트롤러는현재수행중인프로그램을일시중단하고, 인터럽트처리를위한프로그램을수행한후에다시원래의프로그램으로복귀 ISR(Intertupt Service Routine ) 또는 Interrupt handler : 인터럽트처리하는프로그램 2
7.1 인터럽트 (Interrupt) 개요 주프로그램과인터럽트프로그램의차이 < 인터럽트가없는프로그램실행 > < 인터럽트가있는프로그램실행 > 인터럽트가발생할때주프로그램은일시적으로정지하고 ISR로분기하고, ISR이실행되고연산이수행된후에 ISR 프로그램이종료되면, 주프로그램의중지된부분부터다시수행 인터럽트의종료는 인터럽트로부터의복귀 (return from interrupt):rett 명령에의해수행 Background/Foreground 3
7.1 인터럽트 (Interrupt) 개요 인터럽트의종류 인터럽트발생원인에의한분류 : 마이크로컨트롤러내부의기능에의해발생 : 마이크로컨트롤러외부에부가된소자에의해발생 4
7.1 인터럽트 (Interrupt) 개요 인터럽트처리방식에의한분류 일반적인인터럽트 (/INT) 프로그램에의하여인터럽트의요청을받아들이지않고무시할수있는구조의인터럽트 (maskable interrupt) 를의미 우선처리메커니즘 우선처리메커니즘의경우보통인터럽트를허용하는방법은인터럽트마스크레지스터또는인터럽트허용레지스터를사용하여각각의인터럽트를개별적허용하고이것들을다시전체적으로허용함. 차단불가능인터럽트 (/NMI) 프로그램에의해어떤방법으로도인터럽트요청이차단될수없는인터럽트 (non-maskable interrupt) 를의미 전원이상이나비상정지스위치등과같이시스템에치명적인오류를대비하기위해주로사용 5
7.1 인터럽트 (Interrupt) 개요 인터럽트의제어및처리절차 벡터형인터럽트 인터럽트가발생할때마다인터럽트를요청한장치가인터럽트벡터를마이크로컨트롤러에게전송하는방식각주변장치가각각의인터럽트신호선을가지고있고, 각주변장치가인터럽트를요청하면마이크로컨트롤러는각각의인터럽트에따라미리지정된인터럽트벡터를가지고있어즉시해당인터럽트서비스루틴을찾아가는방식 인터럽트처리응답시간이빠르고, AVR에구현된방식 인터럽트의우선순위 2개이상의주변장치가동시에마이크로컨트롤러에인터럽트를요구하는경우우선순위를미리정하여번에하나의인터럽트를선택하여처리우선순위가높은인터럽트의처리중 -> 낮은순위의인터럽트는대기상태우선순위가높은인터럽트의처리끝 -> 낮은순위의인터럽트는미리지정된우선순위에의해처리 6
7.1 인터럽트 (Interrupt) 개요 인터럽트처리순서 Interrupt Vector Table JUMP ISR0 JUMP ISR1 JUMP ISRn IRQ1 요청 Main 프로그램복귀 1 IVT 참조 2 3 5 JUMP ISR Application Program ISR 실행 ISR0 ISR1 ISRn 4 Interrupt Service Routine 7
7.2 ATmega128 의인터럽트구성 인터럽트의종류 리셋을포함하여총 35 종의인터럽트소스가존재 외부인터럽트 8 개, 타이머 / 카운터0에관련된인터럽트 2개 타이머 / 카운터1에관련된인터럽트 5개 타이머 / 카운터2에관련된인터럽트 2개 타이머 / 카운터3에관련된인터럽트 5개 USART0와 USART1에관련된인터럽트각각 3개와기타의인터럽트 6개 인터럽트의동작형태 인터럽트가발생하면관련플래그비트를 1 로세트하여트리거시키는형태 프로그램카운터가실제인터럽트벡터로지정되어인터럽트처리루틴을수행 해당플래그는하드웨어에의해자동으로 0으로클리어됨. 인터럽트플래그는해당비트에 1을써넣음으로써 0으로클리어할수있음. 인터럽트마스크레지스터또는 SREG 레지스터를통해금지상태로설정하여놓았더라도인터럽트가발생하면해당인터럽트플래그가 1로설정되어인터럽트대기상태로되며, 나중에인터럽트가허가상태로설정될때해당인터럽트가처리됨. 인터럽트조건이발생한동안에만인터럽트를트리거하는형태 인터럽트는인터럽트발생조건이사라지면인터럽트요청도없어지므로나중에인터럽트가다시허용상태로되더라도인터럽트는요청되지않음. 8
7.2 ATmega128 의인터럽트구성 (1) 인터럽트의종류및인터럽트벡터 벡터번호 ( 우선순위 ) 벡터주소인터럽트소스인터럽트발생조건 0 0x0000 RESET 외부핀, 전원투입리셋, 저전압검출리셋, 워치독리셋, JTAG AVR 리셋 1 0x0002 INT0 외부인터럽트 0 2 0x0004 INT1 외부인터럽트 1 3 0x0006 INT2 외부인터럽트 2 4 0x0008 INT3 외부인터럽트 3 5 0x000A INT4 외부인터럽트 4 6 0x000C INT5 외부인터럽트 5 7 0x000E INT6 외부인터럽트 6 8 0x0010 INT7 외부인터럽트 7 9 0x0012 TIMER2 COMP 타이머 / 카운터2 비교일치 10 0x0014 TIMER2 OVF 타이머 / 카운터2 오버플로우 11 0x0016 TIMER1 CAPT 타이머 / 카운터1 입력캡처 12 0x0018 TIMER1 COMPA 타이머 / 카운터1 비교일치 A 13 0x001A TIMER1 COMPB 타이머 / 카운터1 비교일치 B 14 0x001C TIMER1 OVF 타이머 / 카운터1 오버플로우 15 0x001E TIMER0 COMP 타이머 / 카운터0 비교일치 9
7.2 ATmega128 의인터럽트구성 (2) 인터럽트의종류및인터럽트벡터 벡터번호 ( 우선순위 ) 벡터주소 인터럽트소스 인터럽트발생조건 16 0x0020 TIMER0 OVF 타이머 / 카운터0 오버플로우 17 0x0022 SPI, STC SPI 시리얼통신완료 18 0x0024 USART0, RX USART0, 수신완료 19 0x0026 USART0, UDRE USART0, 데이터레지스터비움 20 0x0028 USART0, TX USART0, 송신완료 21 0x002A ADC ADC 변환완료 22 0x002C EE READY EEPROM 준비 23 0x002E ANALOG COMP 아날로그비교기 24 0x0030 TIMER1 COMPC 타이머 / 카운터 1 비교일치 C 25 0x0032 TIMER3 CAPT 타이머 / 카운터 3 입력캡처 26 0x0034 TIMER3 COMPA 타이머 / 카운터 3 비교일치 A 27 0x0036 TIMER3 COMPB 타이머 / 카운터 3 비교일치 B 28 0x0038 TIMER3 COMPC 타이머 / 카운터 3 비교일치 C 29 0x003A TIMER3 OVF 타이머 / 카운터 3 오버플로우 30 0x003C USART1, RX USART1, 수신완료 31 0x003E USART1, UDRE USART1, 데이터레지스터비움 32 0x0040 USART1, TX USART1, 송신완료 33 0x0042 TWI I2C 통신인터페이스 34 0x0044 SPM READY 저장프로그램메모리준비 10
7.2 ATmega128 의인터럽트구성 리셋및인터럽트벡터의배치 BOOTRST IVSEL 리셋벡터주소인터럽트벡터의시작주소 1 0 0x0000 0x0000 1 1 0x0000 부트리셋주소 + 0x0002 0 0 부트리셋주소 0x0002 0 1 부트리셋주소부트리셋주소 + 0x0002 리셋및인터럽트벡터는 BOOTRST와 IVSEL 비트의조합에의해가변적으로배치 부트리셋주소 : 부트로더섹션의크기의설정에따라달라짐. ( 표 2.22 참조 ) 예 ) BOOTSZ1 0 = 00 이면부트사이즈는 1024워드로되어부트리셋주소는 0x1C00이됨. 일반적인 ATmega128에서는 BOOTRST 비트는 1로설정되고, IVSEL은 0으로설정 11
7.2 ATmega128 의인터럽트구성 인터럽트벡터의배치 인터럽트벡터를응용프로그램섹션과부트로더섹션사이에서이동하기위해서는 MCU 컨트롤레지스터 (MCUCR, MCU Control Register) 를사용 MCUCR 레지스터의비트구성은아래와같으며, 여기서 IVSEL과 IVCE 비트가이상의목적으로사용되고, 나머지는외부인터럽트를개별적으로허가하는용도로사용 IVSEL과 IVCE 비트를사용 IVSEL ( 인터럽트벡터선택, Interrupt Vector Select) IVSEL = 0 : 인터럽트벡터는응용프로그램섹션인플래시메모리의시작부분에위치 IVSEL = 1 : 인터럽트벡터는부트로더섹션의시작부분에위치 IVCE ( 인터럽트벡터변경허가, Interrupt Vector Change Enable) IVSEL 비트의변경을허가하기위해서 IVCE 비트는 1로설정되어있어야함. 12
7.2 ATmega128 의인터럽트구성 외부인터럽트의개요 8 개의외부인터럽트입력 : INT0~7 INT1 와 INT0 은상승 / 하강에지및 Low 상태에의해인터럽트발생 INT0~7이에지방식에의한인터럽트발생방법으로설정되면, I/O클럭에동기를맞추어인터럽트가발생 INT0~7이레벨변화방식으로설정되고, 에지트리거방식으로설정된 INT2와 PCINT15~0 핀의변화가일어나는경우의 PCI 인터럽트들은비동기적으로인터럽트가발생비동기적으로발생하는인터럽트들은휴면모드를제외하고슬립모드를해제하는수단으로사용가능 INT7와 INT4가에지방식에의해설정되면이는 I/O 클럭을필요로하므로이것들은 I/O 클럭이차단되는휴면모드이외의슬립모드에서는슬립모드를해제하는수단으로사용할수없음. 레벨변화방식으로사용되는인터럽트가전원차단모드의해제수단으로사용되는경우에는좀더긴인터럽트신호가요구됨. -> 슬립모드를해제하고인터럽트가발생되려면충분히긴시간동안인터럽트신호가 L 상태로입력되어야함. 13
7.2 ATmega128 의인터럽트구성 외부인터럽트제어레지스터 외부인터럽트레지스터 MCUCR EIMSK EIFR EICRA EICRB 설명 MCU 제어레지스터외부인터럽트마스크레지스터외부인터럽트플래그레지스터외부인터럽트트리거방식설정레지스터 (INT0~3) 외부인터럽트트리거방식설정레지스터 (INT4~7) EIMSK 제어레지스터 외부인터럽트마스크레지스터 EIMSK(External Interrupt Mask Regiter) 는인터럽트 INT7~0 을개별적으로허용하는데사용, 1 로설정시인터럽트허용, 0 으로설정시인터럽트금지 <SREG 레지스터의글로벌인터럽트허용비트 I 가 1 로되어야만실제허용가능 > 14
7.2 ATmega128 의인터럽트구성 EIFR 제어레지스터 외부인터럽트플래그레지스터 EIFR(External Interrupt Flag Register) 는 INT7~0핀에인터럽트신호가입력되어, 해당인터럽트가트리거되었음을표시하는데사용한다. 이비트들은인터럽트처리가시작되고마이크로콘트롤러가인터럽트벡터를인출하여인터럽트서비스루틴으로점프하게되면다시 0으로클리어된다. 강제로 0을클리어하려면, 해당비트에 1을라이트하면된다. 15
7.2 ATmega128 의인터럽트구성 EICRA 제어레지스터 외부인터럽트 INT3~0 핀으로입력되는신호에대한인터럽트트리거방법을설정 모든레벨트리거인터럽트와 INT3~0 이하강또는상승에지트리거방식으로설정시인터럽트가클럭신호와관계없이비동기적으로검출, 슬립모드를해제하는수단으로사용가능. ISCn1 ISCn0 인터럽트발생방식 0 0 INTn 핀의 L상태입력이인터럽트를트리거한다. 0 1 사용하지않음 (Reserved) 1 0 INTn 핀에하강에지의신호가입력시비동기적으로트리거 1 1 INTn 핀에상승에지의신호가입력시비동기적으로트리거 16
7.2 ATmega128 의인터럽트구성 EICRB 제어레지스터 외부인터럽트 INT7~4 핀으로입력되는신호에대한인터럽트트리거방법을설정 INT7~4 이에지트리거방식으로설정시, I/O 클럭이필요하게되므로 I/O 클럭이차단되는 IDLE 모드이외의슬립모드에서는슬립모드를해제하는수단으로사용불가 ISCn1 ISCn0 인터럽트발생방식 0 0 INTn 핀의 L상태입력이인터럽트를트리거한다. 0 1 INTn 핀의하강에지또는상승에지가인터럽트를트리거한다. 1 0 INTn 핀에하강에지의신호가인터럽트를트리거 1 1 INTn 핀에상승에지의신호가인터럽트를트리거 에지트리거로사용되는인터럽트신호의최소신호폭은 50ns 이상이어야함. 17
7.3 ATmega128 의인터럽트처리 인터럽트처리메카니즘 인터럽트가발생하였을때 MCU 내부에서의동작 현재명령어의수행을마침 스택에 PC를저장 현재인터럽트상태를내부적으로저장 다른인터럽트가받아들여지지는않는다. 즉, 블록킹됨 ISR의벡터주소가 PC에적재됨 ISR이수행 ISR 은인터럽트로복귀 (RETI) 명령어로끝나게된다. 이명령으로인해스택으로부터 PC 의이전값과인터럽트상태의이전값을되찾게되어, 주프로그램의수행이중단되었던곳부터다시계속수행함. 18
7.3 ATmega128 의인터럽트처리 ATmega 128 의인터럽트처리메카니즘 ATmega128 에서의인터럽트처리는정해진우선순위에의해처리 ATmega128 에서는여러인터럽트기동시에발생하였을때우선순위가높은인터럽트가먼저처리되고, 이우선순위는변경이불가능 인터럽트가발생하면인터럽트에해당하는플래그비트가세트, 이플래그비트에의해인터럽트가요청, 전체인터럽트허가비트 I 와해당인터럽트허가비트가모두 1 로설정되어있으면, 인터럽트가요청되어인터럽트벡터의주소를찾아가인터럽트서비스루틴 (ISR) 을수행하게됨 ISR 이수행되고있을때, ATmega128 은자동적으로전체인터럽트허가비트 (SREG 의 I 비트 ) 를클리어모든인터럽트의발생을금지서비스루틴의종료와함께인터럽트를허용 ATmega128 이 RETI 명령에의하여 ISR 의실행을마치고주프로그램으로복귀하는데에도 4 클럭사이클이소요된다. 이시간동안에 PC 의값이스택으로부터복구됨 19
7.4 Code Vision 을이용한 ISR 의작성 ISR 의작성 인터럽트의서비스는벡터주소라는교유번지에서시작 인터럽트벡터에는인터럽트기능을서비스하기위한프로그램이위치해있어야함 인터럽트서비스루틴이호출되기위해서는 C 언어에서인터럽트서비스루틴이올바르게선언되어있어야한다. 인터럽트서비스루틴의선언 : interrupt [n] void int_func_name (void) 타이머 0 의오버플로우인터럽트에대한인터럽트서비스루틴의작성예 // Called automatically on TIMER0 overflow unsigned int interrupt_cnt; unsigned char second; interrupt [18] void timer0_overflow(void) if (++interrupt_cnt == 4000) // count to 4000 second++; // second counter Interrupt_cnt = 0; // clear int counter 20
7.4 Code Vision 을이용한 ISR 의작성 인터럽트의허가및금지방법 인터럽트를사용하려면전체인터럽트허가비트 (SREG의 I 비트 ) 를 1로설정 SREG의 I를이용하여전체인터럽트를허가함. SREG = 0x80; // SREG의 7비트를 1로설정하여전체인터럽트를허가함 어셈블리명령어를이용하여인터럽트를허가하고금지하는방법 sei와 cli의명령어를사용 #asm("sei"); // 전체인터럽트허가 #asm("cli"); // 전체인터럽트금지 #define 전처리기를이용하여 C 언어함수로구현하는방법 <mega162.h> 에포함하여사용 #define sei() (#asm("sei")) #define cli() (#asm("cli")) 21
7.5 인터럽트를이용한실험 ISR 의초기화과정 EIMSK 레지스터의비트설정을통한사용하고자하는인터럽트의허가 EICRA 레지스터의비트설정을통한인터럽트트리거방식설정 SREG의 I 비트의설정을통한전체인터럽트를허가 예 ) 외부 INT0 핀의신호가하강에지에의해인터럽트를발생하도록초기화하는과정 void Interrupt_init(void) EIMSK = 0x01; // INT0 비트설정 ( 외부인터럽트0 허가 ) EICRA = 0x02; // ISC01 =1, ISC00=1( 외부인터럽트 0 하강에지비동기트리거 ) sei(); // 전체인터럽트허가 22
7.5 인터럽트를이용한실험 EICRA 레지스터는그림과같은비트구성을가지고있으므로각비트명에대해다음과같이선언 #define ISC00 0 #define ISC01 1 #define ISC10 2 #define ISC11 3... ISC01 비트만 1로설정하기위한과정 왼쪽시프트연산자 << 를사용 1<<ISC01 ISC01은 1이므로 1<<1 // 0b00000001을 1비트시프트 0b00000010 최종적으로 MCUCR의 ISC01 비트가세트됨 23
7.5 인터럽트를이용한실험 EICRA 레지스터의 ISC01 과 ISC00 을세트하는프로그램 EICRA = 1<<ISC01 1<<ISC00; 이상의비트제어를통해인터럽트초기화함수 Interrupt_init() 의프로그램을재작성 void Interrupt_init(void) EIMSK = 0x01; EICRA = 1<<ISC01 1<<ISC00; sei(); 24
7.5 인터럽트를이용한실험 예제 7-1: 폴링방식의프로그램과인터럽트프로그램의차이점 PORTB 의스위치의신호를계수하여 PORTB 의 LED 에카운트된값을출력하는프로그램작성 #include <mega128.h> #include <delay.h> Byte count, change; bit key7; Byte Exch(void) while(1) key7 = PINB.7; if(key7 == 0) count++; delay_ms(1000); return 1; void main(void) // count 변수의선언및초기화 Count = 0; ex = 0; // 포트 B 의상위니블을입력, 하위니블을출력으로설정 // 포트 B 의 LED 를모두 OFF DDRB = 0x0f; PORTB = 0x0f; while(1) key7 = PINB.7; if(change == 0 && key7 == 1) change = Exch(); if(change == 1 && key7 == 1) change = 0; PORTB = ~(count&0x0f); If(count>= 15) count = 0; 25
7.5 인터럽트를이용한실험 26
7.5 인터럽트를이용한실험 예제 7-2: 외부인터럽트 0 서비스루틴의작성 - 외부인터럽트실험회로 - 27
7.5 인터럽트를이용한실험 PORTB 에연결된스위치대신에 INT0 핀에연결된스위치의입력을계수하여 PORTB 의 LED 에출력하는프로그램작성 #include <mega128.h> #include <delay.h> Byte count; void main(void) DDRB = 0x0f; DDRD = 0x00; interrupt [EXT_INT0] void ext_int0(void) count++; void Interrupt_init(void) EIMSK = 0x01; EICRA = 1<<ISC01 1<<ISC00; sei(); count = 0; Interrupt_init(); while(1) PORTB = ~count; if(count >= 15) count = 0; 28
7.5 인터럽트를이용한실험 EIMSK = 0x01; EICRA = 1<<ISC01 1<<ISC00; SREG = 0x80; DDRB=0x0f; DDRD=0x00; Count=0; 29
7.5 인터럽트를이용한실험 예제 7-3: 외부인터럽트 0 서비스루틴의작성 ( 인터럽트모드의변경 ) 회로에서 INT0 핀에 Low 신호가입력되면 PORTB 포트에연결되어있는모든 LED 를켜고, 인터럽트가해제되면 LED 는 off 상태를그대로유지하는프로그램작성 #include <mega128.h> #include <delay.h> bit exchange; interrupt [EXT_INT0] void ext_int0(void) exchange = ~exchange; void main(void) DDRB = 0x0f; DDRD = 0x00; Interrupt_init(); PORTB = 0x0f; exchange = 0; void Interrupt_init(void) EIMSK = 0x01; EICRA = 1<<ISC01 1<<ISC00; sei(); while(1) if(exchange) PORTB = 0x00; else PORTB = 0x0f; 30
7.5 인터럽트를이용한실험 예제 7-4: 외부인터럽트 0 의활용 LED 가처음에는시프트동작을수행하고있다. 이상황에서외부 INT0 키가눌릴때마다반대의순서로 LED 점등하도록하는프로그램작성 #include <mega128.h> #include <delay.h> bit Direction; interrupt [EXT_INT0] void ext_int0(void) Direction = ~Direction; void PB_LShift(void) int i; Byte Temp; Temp = 0xfe; for(i=0; i<4;i++) delay_ms(500); PORTB = Temp; Temp = (Temp<<1) 0x01; void PB_RShift(void) int i; Byte Temp; Temp = 0xef; for(i = 0; i < 4; i++) delay_ms(500); Temp = (Temp >> 1); PORTB = Temp; void Interrupt_init(void) EIMSK = 0x01; EICRA = 1<<ISC01 1<<ISC00; sei(); void main(void) DDRB = 0x0F; DDRD = 0x00; Interrupt_init(); PORTB = 0x0f; Direction = 0; while(1) if(direction) PB_RShift(); else PB_LShift(); 31