C\C++/임베디드 시스템

임베디드시스템 포토센서를 활용한 외부 인터럽트 제어

sundori 2023. 11. 18. 22:30

외부 인터럽트

미리 배정되어 있는 처리기의 핀으로 입력되는 트리거 신호에 의해 발생하는 인터럽트이다.

프로그램에 의해 발생하는 타이머/카운터 인터럽트와 비교하면 외부 인터럽트는 하드웨어적인 인터럽트라 할 수 있고

주변 장치들의 요청에 가장 신속하게 대처할 수 있는 인터럽트의 대응 방식이다.

글쓴이가 공부할 때 사용하는 ATmega128 보드 에서는 ...

외부 인터럽트 관련 레지스터

외부 인터럽트 마스크 레지스터 : EIMSK("External Interrupt Mask Register")

EIMSK 레지스터는 외부 인터럽트를 사용하거나 무시할지를 제어하는 데 사용하는데, 외부 인터럽트는 외부에서 발생하는 신호나 이벤트에 응답하여 마이크로컨트롤러의 실행을 중단하고 특정한 인터럽트 서비스 루틴(ISR)을 실행하게 해 준다.

EIMSK 레지스터는 일반적으로 각 비트가 특정한 외부 인터럽트 번호에 대응하며, 이를 통해 해당 인터럽트를 활성화 또는 비활성화할 수 있고, 레지스터의 상태에 따라 외부 인터럽트가 처리될 것인지에 대한 여부가 결정된다.

 

예를 들어, EIMSK 레지스터의 0번 비트를 설정하면 (비트를 1로 설정하면), 외부 인터럽트 0이 활성화되고, 클리어하면 (비트를 0으로 설정하면) 비활성화된다. 이를 통해 프로그래머는 특정 인터럽트에 대한 반응을 조절할 수 있습니다.

Bit 7 6 5 4 3 2 1 0 EIMSK
  INT7 INT6 INT5 INT4 INT3 INT2 INT1 INT0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial

0 0 0 0 0 0 0 0

코딩 예 : EIMSK = 0x11;

외부 인터럽트 제어 레지스터들 : EICRA, EICRB

  • EICRA (External Interrupt Control Register A): 외부 인터럽트 EIMSK에서 INT0 ~INT3번 핀에 입력되는 트리거 신호의 유형을 설정하기 위해 사용하는 레지스터로서 보통 비트 쌍마다 하나의 외부 인터럽트에 대한 설정이 할당되며, 비트 위치에 따라 상승 에지, 하강에지, 레벨 트리거 등 선택할 수 있다.
Bit 7 6 5 4 3 2 1 0 EICRA
  ISC31 ISC30 ISC21 ISC20 ISC22 ISC10 ISC01 ISC00
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial

0 0 0 0 0 0 0 0
ISCn1 ISCn0 트리거 신호에 따른 동작 (INT3 ~ INT0)
0 0 로우 레벨일 때 인터럽트 요청 발생
0 1 Reserved
1 0 하강 에지에서 인터럽트 요청 발생
1 1 상승 에지에서 인터럽트 요청 발생

예를 들어 INT0 트리거의 신호를 하강 에지로 설정하고자 한다면, EICRA 레지스터의 비트 1 ~ 0인 ISC01~ISC00의 값을 1,0으로 결정하면 되는데.... 코딩 예: EICRA  = 0x02;

 

  • EICRB (External Interrupt Control Register B) : 외부 인터럽트 EIMSK에서 INT4 ~INT7번 핀에 입력되는 트리거 신호의 유형을 설정하기 위해 사용하는 레지스터로서 보통 비트 쌍마다 하나의 외부 인터럽트에 대한 설정이 할당되며, 비트 위치에 따라 상승 에지, 하강에지, 레벨 트리거 등 선택할 수 있다.
Bit 7 6 5 4 3 2 1 0 EICRB
  ISC71 ISC70 ISC61 ISC60 ISC51 ISC50 ISC41 ISC40
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial

0 0 0 0 0 0 0 0

이 두 개의 EICRA, EICRB 레지스터의 두 비트인 ISCn1~ISCn0(n은 외부 인터럽트 번호)을 사용하여 인터럽트 트리거 신호를 설정할 수 있다.

ISCn1 ISCn0 트리거 신호에 따른 동작 (INT7 ~ INT 4)
0 0 로우 레벨일 때 인터럽트 요청 발생
0 1 하강 에지 또는 상승 에지에서 인터럽트 요청 발생
1 0 하강 에지에서 인터럽트 요청 발생
1 1 상승 에지에서 인터럽트 요청 발생

외부 인터럽트 플래그 레지스터 : EIFR (External Interrupt Flag Register)

외부 인터럽트가 발생하면, 해당 인터럽트 플래그가 EIFR 레지스터에 설정(1)되는데 이 레지스터를 통해 어떤 외부 인터럽트가 발생했는지를 확인할 수 있으며 SREG 레지스터의 I비트가 1, EIMSK 레지스터의 해당되는 비트가 1로 인터럽트 허용 상태라면 처리기는 인터럽트 서비스 루틴을 실행하면서 EIFR 레지스터의 해당되는 비트를 0으로 클리어한다.

만약 프로그램에 의해 이 플래그를 지우기 위해서는 비트를 1로 설정하면 된다.

Bit 7 6 5 4 3 2 1 0 EIFR
  INTF7 INTF6 INTF5 INTF4 INTF3 INTF2 INTF1 INTF0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial

0 0 0 0 0 0 0 0

상태 레지스터 : SREG (Status Register)

프로세서의 현재 상태를 나타내는 중요한 레지스터로서 각 비트들은 여러 가지 정보를 나타내며, 그중에서도 가장 중요한 것은 (Global Interrupt Enable) 비트 I이다. 이 비트가 설정되면 전역적으로 인터럽트가 활성화되며, 클리어되면 인터럽트가 비활성화되기 때문이다.

  • I (Global Interrupt Enable): 이 비트가 1로 설정되면 전역적으로 인터럽트가 활성화되어 있음을 나타내며 인터럽트 벡터로 진입을 허용하게 되고, 0으로 설정되면 인터럽트가 비활성화된다. I 비트는 인터럽트 처리 루틴 이 시작되면 0으로 바뀌어 다른 인터럽트 처리 루틴이 실행되지 못하도 록 막는 역할을 수행하며, 인터럽트 처리 루틴을 실행하고 빠져나갈 때 다 시 1로 바뀌게 된다. 프로그래머가 CLI 명령으로 0 으로, SEI 명령으로 1 로 설정할 수 도 있다.
                                                            SREG = 0X80; 또는 #asm("sei") // 전역 인터럽트 허용
  • T (Bit Copy Storage): 이 비트는 현재 프로세서 상태를 저장하기 위한 용도로 사용되는 비트이다.
  • H (Half Carry Flag): 이 비트는 BCD(이진 부호 없는 십진수) 연산에서 하위 4비트에서 상위 4비트로의 올림을 나타낸다.
  • S (Sign Flag): 연산 결과의 부호를 나타낸다.
  • V (Two's complement overflow indicator): 부호가 있는 덧셈 또는 뺄셈에서 오버플로우가 발생했음을 나타낸다.
  • N (Negative Flag): 연산 결과가 음수임을 나타낸다.
  • Z (Zero Flag): 연산 결과가 0 임을 나타낸다.
  • C (Carry Flag): 덧셈 또는 뺄셈에서 캐리(자릿수 넘김)가 발생했음을 나타낸다.
Bit 7 6 5 4 3 2 1 0 SREG
  I T H S V N Z C
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial

0 0 0 0 0 0 0 0
/* 이 프로그램은 포토센서를 차단하였을 때 LED, RELAY, BUZZER, FND 전부 구동됨. */
#include <mega128.h>
#include <delay.h>

// 매크로로 메모리 주소 정의
#define LED_CON *((unsigned char *)0x8000)
#define SET_CON *((unsigned char *)0x8100)
#define LCD_DATABUS *((unsigned char *)0x8300)

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void) {
    // 외부 인터럽트 0 발생 시 LED, 릴레이, 부저, FND 온
    LED_CON = 0xff;
    SET_CON = 0xff;
    LCD_DATABUS = 0xff;
    delay_ms(1000); // 1초 지연
}

void main(void) {
    DDRB = 0x00; // PORTB를 입력으로 설정
    
    // AVR ATmega128-F Board initialization
    MCUCR = 0x80; // 외부 메모리 및 I/O 컨트롤 활성화
    
    // External I/O initialization
    LED_CON = 0x00;
    SET_CON = 0x00;
    LCD_DATABUS = 0x00;
    
    EICRA = 0x00; // 외부 인터럽트 0 및 1의 트리거 조건을 초기화
    EICRB = 0X00;
    EIMSK = 0X01; // 외부 인터럽트 0 활성화
    EIFR = 0X01;  // 0번 인터럽트를 사용하므로 0번 비트만 1로 설정
    
    #asm("sei") // 전역 인터럽트 활성화
    
    while (1) {
        // 무한 루프에서 LED, 릴레이, 부저, FND를 모두 끔
        LED_CON = 0x00;
        SET_CON = 0x00;
        LCD_DATABUS = 0x00;
    }
}