Language/AVR

ATmega 128 : Led Bar 버튼 인터럽트 동작 구현

짱도르딘 2024. 5. 29. 17:11
728x90

이번에는 인터럽트를 사용하여 LED Bar를 제어하는 동작을 구현해보겠다.

 

인터럽트(Interrupt)란, 외부에서 이벤트가 발생하였을 때 동작하던 프로그램을 잠시 중단하고 해당 이벤트를 동작한 후 다시 프로그램의 동작으로 복귀하는 것을 의미한다.

 

이벤트가 발생하면 마이크로컨트롤러는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(Interrupt Service Routine, ISR)이라고 불리는 특정 함수를 실행한다.

 

ATmega128a Datasheet내 인터럽트에 관한 내용은 다음과 같다.

 

ATmega128a Datasheet_Interrupt
ATmega128a Datasheet_Interrupt_2

 

인터럽트가 발생하였을 때 수행하는 동작은 ISR(Interrupt Service Routine) 함수에서 구현된다.

 

해당 동작을 수행하기 위한 코드는 아래와 같다.

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> // 인터럽트 헤더파일

ISR(INT0_vect) //인터럽트 0번 벡터가 발생하면 불을 킨다, ISR = Interrupt Service Routine
{
	PORTC = 0xff;
	_delay_ms(1000); //버튼 누르면 켜지고, 1초 있다가 꺼진다 
}

int main(void)
{
	DDRC = 0xff; // PORTC 를 출력으로 설정한다 
	sei(); // 전역 인터럽트 활성화
	
	EICRA = 0x02; // INT0번 하강엣지 사용, LOW 사용하고싶으면 0x00, 상승엣지 사용하고 싶으면 0x03으로 사용하면 된다.
	// EICRA |= (1 << ISC01) | (1 << ISC00);
	
	EIMSK = 0x01; // INT0번 인터럽트 인에이블
	// EIMSK |= (1 << INT0);
	
	DDRD = 0x00;
	
    while (1) 
    {
		PORTC = 0x00;
    }
}

 


인터럽트 0번 벡터가 발생한다면, 포트 C는 모두 출력이 된다. 즉 LED Bar가 모두 점등이 된다.

 

main 함수 내에 sei 함수가 호출된 것을 확인할 수 있다. sei 함수는 Global Interrupt를 Enable하는 함수로, 다시말해 전역적으로 인터럽트가 활성화 되는 것을 의미한다.

 

그 밑에는 EICRA(External Interrupt Control Register A)가 선언 된 것을 확인할 수 있다.

 

EICRA에 대한 자세한 내용은 아래와 같다.

 

ATmega128a Datasheet_EICRA

 

EICRA는 ATmega 레지스터 중 하나로, 외부 인터럽트의 동작을 제어하는데에 사용이 된다.

 

EICRA는 8bit 레지스터이며, 각 bit는 외부 인터럽트 핀 INT3:0에 해당된다. 이 레지스터의 비트는 ISCxy라 불리우며 각 핀에 대한 인터럽트 세트업을 결정한다.

 

ISCxy비트는 외부 인터럽트를 발생시키는 조건으로 설정되는데, 주로 레벨 변화 혹은 엣지를 감지할 때 인터럽트를 발생시키는데에 사용된다.

 

작동 모드는 아래와 같다.

 

ATmega128a Datasheet_ISC

 

00일때는 Low Level에서 인터럽트 발생, 10일때는 하강 엣지에서 인터럽트 발생, 11일때는 상승 엣지에서 인터럽트가 발생된다는 것을 확인할 수 있다.

 

위의 코드를 보면 알 수 있듯이 EICRA는 0x02(0b 0000 0010)으로 선언된 것을 확인할 수 있다. 이는 즉 하강 엣지 기능을 사용한다는 것을 확인할 수 있다.

 

 

다음은 EIMSK(External Interrupt Mask Register)에 대해서 알아보도록 한다.

 

ATmega128a Datasheet_EIMSK

 

 

ATmega128a Datasheet_Pinout figure

 

이번 동작을 구현하기 위해서 PD0 핀에 인터럽트를 연결하였다. 위의 Pinout에 대한 정보를 살펴보면 PD0 핀은 INT0 전용 핀인 것을 확인할 수 있다.

 

따라서 우리는 INT0을 활용하기 위해서 위 코드를 보면 알 수 있듯이 EIMSK = 0x01; 로 선언한 것을 확인할 수 있다.

 

 

 

728x90