CHAPTER 7 인터럽트 가. 레지스터구조이해하기 나. 엔코더제어하기
인터럽트 (Interrupt) 범용입출력포트에서입출력의내용을처리하기위해매번입출력을요구하는플래그를검사하는일 (Pollong) 에대하여마이크로컨트롤러에게는상당한시간을소비하게만든다. 인터럽트란 CPU가현재처리하고있는일보다급하게처리해야할사건이발생했을때, 현재수행중인일을중단하고급한일을처리한후에본래의일을다시수행하는것을말한다. 즉, 프로그래밍된순서대로일을처리하는것이아니라발생시기를예측할수없는사건을처리하는데효과적인방법이다. 인터럽트요청이들어오면 CPU는인터럽트를수용할수도있고무시할수도있다. 요청된인터럽트에대해항상응답해야하는인터럽트를마스크불가능 (Non maskable, NMI) 인터럽트라하고, 그렇지않은경우를마스크가능 (Maskable) 인터럽트라한다. 인터럽트가발생하면 CPU는현재수행중인프로그램을멈추고상태레지스터와 PC(Program Counter) 등을스택에잠시저장한후인터럽트서비스루틴 (ISR) 으로점프한다. 인터럽트서비스루틴을실행한후에는이전의프로그램으로복귀하여정상적인절차를실행한다. 인터럽트처리과정은다음과같이요약할수있다. 인터럽트가준비된장치는인터럽트요구플래그비트를세트하고 CPU에게인터럽트를요구한다. CPU는인터럽트확인 (INTA : interrupt acknoledge) 신호를보내고, INTA를받은입출력장치는인터럽트요구 (INTR : interupt request) 신호를삭제한다. CPU는 PC, PSW, 레지스터등을스택에저장한다 (PUSH). CPU 는인터럽트서비스루트 (ISR) 의주소를프로그램카운터 (PC) 에적재한다. 인터럽트서비스루틴을수행한다. PSW, 레지스터등을스택으로부터복귀한다 (POP). 본래의메인프로그램으로복귀한다. AVR ATmega128 마이크로컨트롤러는 RESET 벡터등을합쳐서 35 개의인터럽트 벡터를가지고있으며, 그림 5.1 과같이나타낸다.
[ 그림 5.1] 인터럽트벡터 Vector 번호 프로그램주소 소스 인터럽트 31 $003C USART1, RX USART1, Rx Complete 32 $003E USART1, UDRE USART1, Data register Empty 33 $0040 USART1, TX USART1, Tx Complete 34 $0042 TWI To-ire Serial Interface 35 $0044 SPM READY Store program memory Ready
아래의표는 BOOTRTS 와 IVSEL 비트를조작함으로써 RESET 및인터럽트벡터의 시작주소가변경되는것을나타낸다. BOOTRST IVSEL Reset address Interrupt Vector 시작주소 1 0 $0000 $0002 1 1 $0000 Boot Reset Address + $0002 0 0 Boot Reset Address $0002 0 1 Boot Reset Address Boot Reset Address + $0002 AVR ATmega128의일반적인경우, 즉 BOOTRST = 1이고, IVSEL = 0인경우에해당되는인터럽트벡터주소와이를정의한 AVRStudio에서정의한헤더파일인 iom128.h의내용을살펴보면자세한내용을볼수있다. 그림 5.2는인터럽트벡터를정의한부분을발췌하였다.
[ 그림 5.2] 인터럽트벡터 그리고 BOOTRST = 1, IVSEL = 1 이고, 부트사이즈가 8K 바이트로설정되어있으 면그림 5.3 과같은 RESET 벡터와인터럽트벡터의어드레스가변경됨을알수있 다. [ 그림 5.3] 인터럽트벡터어드레스변경 또한 BOOTRST = 0, IVSEL = 0 이고, 부트사이즈가 8K 바이트로설정되어있으면 그림 5.4 와같은 RESET 벡터와인터럽트벡터의어드레스가변경됨을알수있다.
[ 그림 5.4] 인터럽트벡터어드레스변경 마지막으로 BOOTRST = 0, IVSEL = 1 이고, 부트사이즈가 8K 바이트로설정되어 있으면그림 5.5 와같은 RESET 벡터와인터럽트벡터의어드레스가변경됨을알 수있다. [ 그림 5.5] 인터럽트벡터어드레스변경 가. 레지스터구조이해하기 1) MCUCR(MCU Control Register) 그림 5.6 과같이 MCUCR 레지스터는인터럽트의벡터의위치를설정하고또는외 부메모리를사용할경우에웨이트사이클의개수를설정할때사용한다. [ 그림 5.6] MCUCR 레지스터
IVSEL = 0 : 인터럽트벡터는플래시메모리의시작점 ($0000) 에위치하게된다. IVSEL = 1 : 언터럽트벡터는플래시메모리의 Boot Loader section의시작점으로이동한다. Boot Loader section의시작점의어드레스는 BOOTSZ 비트에의해서결정되며, 인터럽트벡터의예기치않은위험을방지하기위해서 IVSEL 비트를설정하는순서는다음과같다. 1. IVCE(Interrupt Vector Change Enable) 비트에 1 을쓴다. 2. 4 사이클이내에 IVCE = 0으로설정하고, IVSEL에는원하는비트를설정한다. 이와같은순서로실행하면인터럽트는자동으로 disable되는데, 정확하게는 IVCE가 1 로셋되는사이클에서인터럽트가 disable로된다. IVCE = 1 : IVSEL 비트를변경할수있다. IVCE 비트는 IVSEL 비트를변경 하고난후 4 사이클이지나면하드웨어에의해서 0 으로클리어된다. 2) 외부인터럽트 (External Interrupt) AVR ATmega128의외부인터럽트는 INT0~INT7 핀에이벤트가인가됨으로써발생한다. 이벤트 (Event) 는크게레벨방식 (Level mode) 과에지방식 (Edge mode) 으로나뉜다. AVR ATmega128의외부인터럽트는하강에지, 상승에지, Lo level에서발생될때인터럽트가발생된다. 이것을설정하기위해서 EICRA(External Interrupt Control Register A) 와 EICRB(External Interrupt Control Register B) 를선택한다. PE4~PE7, PD0~PD3(INT0~7) 핀이출력으로설정되어있어도인터럽트는발생된다. 즉, DDRn을통해 I/O의방향을별도로설정할필요가없다. EICRA(External Interrupt Control Register A) 그림 5.7 과같이 EICRA 레지스터는 interrupt sense control 및 MCU 의일반적인 기능을설정하는데사용한다. [ 그림 5.7] EICRA 레지스터 외부인터럽트 0~3 은전역인터럽트 (SREG I 비트 ) 와 EIMSK 의개별인터럽트 (INT3~INT0) 를설정함으로써발생된다. 레벨과에지에대해서는아래와같다.
ISCn1 ISCn0 설명 0 0 INTn의 Lo level에서인터럽트를발생한다. 0 1 예약 1 0 INTn의하강에지에서인터럽트를발생한다. 1 1 INTn의상승에지에서인터럽트를발생한다. EICRB(External Interrupt Control Register B) 그림 5.8과같이 EICRB 레지스터는다기능비트로구성되어있다. [ 그림 5.8] EICRB 레지스터 외부인터럽트 4~7 는전역인터럽트 (SREG I 비트 ) 와 EIMSK 의개별인터럽트 (INT7~INT4) 를설정함으로써발생된다. 레벨과에지에대해서는아래와같다. ISCn1 ISCn0 설명 0 0 INTn의 Lo level에서인터럽트를발생한다. 0 1 INTn 핀에논리적인변화가발생할경우에인터럽트가발생한다. 1 0 INTn의하강에지에서인터럽트를발생한다. 1 1 INTn의상승에지에서인터럽트를발생한다. EIMSK(External Interrupt Mask Register) 그림 5.9 와같이 EIMSK 레지스터는 INT0~INT7 의개별인터럽트를설정한다. [ 그림 5.9] EIMSK 레지스터 이레지스터에의비트에 1 을쓰고, SREG 레지스터의 I 비트가 1 로설정 되어있으면외부인터럽트는 enable 된다. EICRA 와 EICRB 레지스터의 ISCn1 과 ISCn0 의비트를설정함으로써에지또는레벨방식을선택할수있다. EIFR(External Interrupt Flag Register)
그림 5.10 과같이 EIFR 레지스터는 EIMSK 레지스터에서설정한개별인터럽트의 상태를나타낸다. [ 그림 5.10] EIFR 레지스터 INT0~INT7 핀에에지또는논리적인변화에서트리거되어인터럽트가요구되면, INTF0~INTF7 비트는 1 로셋된다. SREG 레지스터의 I 비트와 EIMSK 레지스터의 INT0~INT7 비트가 1 로설정되어있으면, MCU는해당하는인터럽트벡터로점프한다. 인터럽트서비스루틴 (ISR) 이실행되면 INTF0~INTF7 비트는자동으로 0 으로클리어되고, 이 INTF0~INTF7 비트에논리적으로 1 을쓰면클리어가되며 INT0~INT7이레벨인터럽트로설정되면 INTF0~INTF7 비트는자동으로클리어된다.
나. 엔코더제어하기 엔코더는그림 5.11과같은원리로동작하게되며, 시계방향으로회전시 B상의 ON신호가 A상의 ON신호보다먼저인식이되어상위신호의출력신호를내보낸다. 그와반대로반시계방향으로회전시 A상의 ON신호가 B상의 ON신호보다먼저인식되어하위신호의출력신호를내보낸다. 각각의출력신호를 ATmega128의입력신호로간주되어읽어들어카운트동작에따라모터회전축의위치정보를얻어낼수있다. [ 그림 5.11] 엔코더동작원리 1) 활용실습 Q : 5.1_ 손으로로봇을밀어오른쪽모터에서발생되는엔코더값을 A 상과 B 상 으로나누어도트매트릭스에출력하기 A : #include<avr/io.h> #include <avr/signal.h>
SIGNAL(SIG_INTERRUPT0) PORTA=0xE0; PORTC=PIND&0xFE; SIGNAL(SIG_INTERRUPT1) PORTA=0x07; PORTC=PIND&0xFD; void main(void) DDRA=0xFF; DDRC=0xFF; DDRD=0x00; EIMSK =0x03; EICRA =0x0F; EIFR =0x03; sei(); hile(1); 참고 : 그동안학습한내용을기반으로프로그램을작성하시오. Q : 5.2_ 손으로로봇을밀어왼쪽모터에서발생되는엔코더값을 A 상과 B 상으 로나누어도트매트릭스에출력하기 A :
#include<avr/io.h> #include <avr/signal.h> SIGNAL(SIG_INTERRUPT2) PORTA=0xE0; PORTC=PIND&0xFB; SIGNAL(SIG_INTERRUPT3) PORTA=0x07; PORTC=PIND&0xF7; void main(void) DDRA=0xFF; DDRC=0xFF; DDRD=0x00; EIMSK =0x0C; EICRA =0xF0; EIFR =0x0C; sei(); hile(1); Q : 5.3_ 손으로로봇을밀어양쪽모터에서발생되는엔코더값을 A 상과 B 상으 로 2 줄씩나누어도트매트릭스에출력하기
A : #include<avr/io.h> #include <avr/signal.h> unsigned int mrcnta=0, mrcntb=0, mlcnta=0, mlcntb=0; void m_delay(unsigned int k) unsigned int i, j; for(i=0; i<100; i++) for(j=0; j<k; j++); SIGNAL(SIG_INTERRUPT0) PORTA=0x03; PORTC=mrcnta; m_delay(1); mrcnta++; SIGNAL(SIG_INTERRUPT1) PORTA=0x0C; PORTC=mrcntb; m_delay(1); mrcntb++; SIGNAL(SIG_INTERRUPT2) PORTA=0x30; PORTC=mlcnta; m_delay(1); mlcnta++;
SIGNAL(SIG_INTERRUPT3) PORTA=0xC0; PORTC=mlcntb; m_delay(1); mlcntb++; void main(void) DDRA=0xFF; DDRC=0xFF; DDRD=0x00; EIMSK =0x0F; EICRA =0xFF; EIFR =0x0F; sei(); hile(1); 2) 응용문제 1 왼쪽모터의엔코더 A 상에서인터럽트가발생하면단일 LED 1 번을켜고오른 쪽모터의엔코더 B 상에서인터럽트가발생하면단일 LED 3 번을켜기