- 인터럽트의 개요
- 인터럽트 처리 과정
- ATMega128 Interrupt Vectors
- External interrupt
- External Interrupts를 사용 하기 위한 설정
- External Interrupt Control Register
- EICRA - External Interrupt Control Register A
- EICRB - External Interrupt Control Register B
- EIMSK - External Interrupt Mask Register
- EIFR - External Interrupt Flag Register
- Interrupt를 사용하는 Program 작성하기
- External Interrupt를 이용하는 Program 예
- ATMega128 External Interrupt - ASM 관련 페이지 보기
- 인터럽트의 개요
- Interrupt : 외부 장치의 요구에 의해서 현재 실행 중인 프로그램을 잠시 멈추고, Interrupt에 의하여 요구된 작업을 먼저 수행한 후에 다시 원래의 프로그램으로 복귀하여 실행 한다.
- 주변장치의 서비스 요청에 맞추어(동기 하여) 서비스를 실행 한다.
- Embedded System의 Program은 대부분 Interrupt Drive 방식으로 작성 한다.
- Interrupt Processing 예
- 인터럽트 처리 과정
- Program 실행 중에 Interrupt가 발생(서로 다른 Interrupt는 Interrupt 번호로 구분) 하면(Interrupt 실행이 허용 된 경우(Interrupt Enable 상태인 경우)),
- 현재 실행 중인 Program을 잠시 중단 하고(Interrupt Service Routine이 종료 된 다음 현재 실행이 종료된 다음 명령어 부터 실행 할 수 있도록 하기 위하여 다음에 실행 할 명령의 위치를 Stack에 저장 하고),
- Interrupt Vector Table에서 Interrupt Service Routine의 시작 번지(Interrupt 번호를 이용 하여 Interrupt Vector Table에서 Service Routine의 시작 번지 알 수 있다.)를 획득 하여
- Interrupt Service Routine으로 Jump 한다.
- Interrupt Service Routine의 실행이 종료 되면 Stack에 저장된 다음에 실행 할 명령의 Address를 이용 하여 Interrupt 발생 이전에 실행 하던 Program을 계속 하여 실행 한다.
- ATMega128 Interrupt Vectors
- External interrupt
- External interrupt 0 - 3( Port D)
- External interrupt 4 - 7( Port E)
- External Interrupts를 사용 하기 위한 설정
- INTn(n은 0 - 7)
- Port D를 사용 하는 Interrupt: PD0(INT0), PD1(INT1), PD2(INT2), PD3(INT3)
- Port E를 사용 하는 Interrupt: PE4(INT4), PE5(INT5), PE6(INT6), PE7(INT7)
- External Interrupt을 사용하기 위한 설정
- 사용하고자 하는 Port를 입력으로 설정. Push Button Switch 등을 사용하는 경우 Input Port PullUp을 Enable 한다.
- External Interrupt의 mode 설정
- External Interrupt를 Enable 한다.
- External Interrupt Mask Register 에서 사용하고자 하는 INT를 Set(Enable) 한다.
- Global Interrupt Enable
- Status Register (SREG)의 I-bit(Global Interrupt Flag)를 Set(Enable) 함
- Interrupt 0를 사용(Push Button Switch(PD0)의 입력) 하기 위한 초기화 설정 예
- External Interrupt Control Register
- EICRA - External Interrupt Control Register A
- EICRB - External Interrupt Control Register B
- EIMSK - External Interrupt Mask Register
- INT7~0 Interrupt를 개별적으로 허용하는데 사용
- 허용 : 1 , 금지 : 0
- EIFR - External Interrupt Flag Register
- INT7 ~ 0 Pin에 Interrupt 신호가 입력되면 해당 Flag가 Set되어 Interrupt가 Trigger 되었음 표시
- 해당 Interrupt routine이 실행되면 0으로 Cleared 됨
- 또는 해당 Flag에 1을 Write 하면 0으로 Cleared 됨
- Interrupt를 사용하는 Program 작성하기
- Hardware Interrupt Vector Table
- ATMega128 Interrupt Vector Table의 예: "avr128_interrupt_table.inc"
- 위 예에는 RESET(Microprocessor에 Hardware RESET 신호가 인가되는 경우 이 Interrupt가 발생함) Interrupt Vector만 설정되어 있다.
- Interrupt Vector Table에는 하나의 Interrupt에 2 Word(4 Byte)가 활당되어 있다. 특정한 Interrupt를 사용하는 경우 Interrupt Service Routine(ISR)을 작성하고 Interrupt Vector Table의 해당 위치에 ISR로 jmp 하는 명령(2 Word)을 작성한다. 위 예는 RESET Interrupt가 발생하면 RESET Label 위치의 ISR을 실행하도록 설정(jmp RESET)한 예 이다.
- 사용하지 않는 Interrupt의 Vector Table에는 보통 reti(1 Word) 와 nop(1 Word) Instruction Code를 삽입한다. 연속한 reti, nop Instruction에는 2 Word(4 Byte)가 활당되어 각 장치의 Interrupt 번호에 2를 곱한 번지에 해당 Interrupt의 Interrupt Vector(ISR 번지로 jmp 하는 Code)가 위치하게 된다.
- 사용하지 않는 Interrupt의 Vector Table에는 reti 와 nop Instruction Code를 삽입하면 잘못된 Interrupt 가 발생한 경우 바로 잘못된 Interrupt를 종료(reti) 시키는 효과가 있다.
- Interrupt Service Routine
- Interrupt Service Routine(ISR)의 첫번째 위치에는 Interrupt Vector Table에서 Jmp 명령을 사용하여 이 ISR을 실행할 수 있도록 Label 이 있어야 한다.
- Interrupt Service Routine(ISR)의 마지막 위치에는 ISR을 종료하는 reti 명령이 있어야 한다.
- Interrupt Service Routine(ISR)의 앞 부분에는 ISR로 Jmp 하기 이전 프로그램 실행의 연속성이 손상되지 않도록 ISR에서 사용하는 Register를 push 명령을 사용하여 Stack에 저장하여 보호하여야 한다. push 명령을 사용하여 Stack에 저장한 Register는 ISR 이 종료되기 직전에 pop 명령을 사용하여 복원하고 reti 명령을 실행하여야 한다.
- Interrupt Service Routine의 기본 구조 예
- Interrupt Vector 설정하기
- AVR Assembly 프로그램의 Interrupt Vector 설정
- Project를 생성하고 위 "ATMega128 Interrupt Vector Table의 예"를 Download 하여 avr128_interrupt_table.inc 파일을 main.asm이 있는 폴더에 복사한다 한다.
- Interrupt Service Routine(ISR)을 작성한다.
- avr128_interrupt_table.inc 파일을 편집하여 Interrupt Vector를 설정(ISR의 LABEL 이용)한다.
- External Interrupt INT0를 사용하기 위한 Interrupt Vector를 설정 예
- GCC Assembly 프로그램의 Interrupt Vector 설정
- External Interrupt를 이용하는 Program 예
- Switch를 누른 회수를 LED Bar에 2진수로 출력 하는 프로그림 예
- External Interrupt(PD0)를 이용하여 Switch를 누른 회수를 LED Bar에 2진수로 출력 하는 프로그림 예: AVR_asm_sw_bounce_counter_ext_int.zip
- 실험을 위한 준비
- PD0에 Push button switch를 연결한다.
- PORTF에 저항(330Ω)과 LED Array(8Bits)를 연결한다.
- 실험 방법
- Project(Project name: AVR_asm_sw_bounce_counter_ext_int)를 생성 한다.
- 위 프로그램을 main.asm에 복사하고 저장한다.
- INT0 Interrupt Vector 설정: "avr128_interrupt_table.inc"를 다운로드하여 위 "External Interrupt INT0를 사용하기 위한 Interrupt Vector를 설정 예"와 같이 편집한다.
- Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR_asm_sw_bounce_counter_ext_int.hex 파일이 생성된다.
- AVR_asm_sw_bounce_counter_ext_int.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
- 실험: Push button switch(PD0)를 누르면 LED Array(8Bits)에 누른 회수가 2진수로 출력된다.
- External Interrupt를 이용하여 LED의 회전 방향을 제어 하는 Program 예
- External Interrupt(PD0와 PD1)를 이용하여 LED의 회전 방향을 제어 하는 Program 예: AVR_asm_led_shift_ext_int.zip
- 실험을 위한 준비
- PD0와 PD1에 Push button switch를 연결한다.
- PORTF에 저항(330Ω)과 LED Array(8Bits)를 연결한다.
- 실험 방법
- Project(Project name: AVR_asm_led_shift_ext_int)를 생성 한다.
- 위 프로그램을 main.asm에 복사하고 저장한다.
- INT0, INT1 Interrupt Vector 설정: "avr128_interrupt_table.inc"를 다운로드하여 아래 예와 같이 편집한다.
- Build → Build Solution 를 실행 하면 main.asm File 이 Assemble 되어 AVR_asm_led_shift_ext_int.hex 파일이 생성된다.
- AVR_asm_led_shift_ext_int.hex 파일을 Target Board에 Upload 하고 프로그램을 실행한다.
- 실험: Push button switch(PD0)를 누르면 LED 가 좌측으로 회전하고, Switch(PD1)를 누르면 LED 가 우측으로 회전한다.
Main Routine 실행 중 Interrupt 요구가 발생 하면 현재 실행 중인 Routine을 잠시 멈추고 Interrupt Service Routine으로 Jump 하여 Interrupt Service을 실행 하고, Interrupt Service 종료 후 다시 Main Routine 실행 한다.
아래 표는 ATMega128에서 사용 하는 Interrupt의 종류와 Interrupt 번호, 각 Interrupt(Interrupt 번호에 따른) Service Routine의 시작 번지를 저장 하는 Memory 번지, 그리고 각 Interrupt에 대한 요약된 설명 이다.
ATMega128는 External Interrupt와 Timer/Counter, USART 등 다양한 Interrupt Source를 사용 하지만 이 페이지에서는 External Interrupt만 설명 하고, 기타 Interrupt는 각 장치를 설명 하는 부분에서 설명 한다.
아래 표를 참고 하여 Interrupt Vector Table을 작성 할 수 있다.
아래 표는 External Interrupt 0번 - 3번이 사용 하는 Pin에 대한 설명이다.
External Interrupt 0번 - 3번은 Port D의 PD0 - PD3번(이 Pin을 Input Port(Pin)으로 사용 하는 경우에만 External Interrupt 신호를 입력 받는 Pin으로 사용 할 수 있다.) Pin을 사용 한다. 이 Pin은 표와 같이 해당 Port가 Input Port로 사용 되지 않는 경우 다른 장치들이 사용 할 수 있다.
아래 표는 External Interrupt 4번 - 7번이 사용 하는 Pin에 대한 설명이다.
External Interrupt 4번 - 7번은 Port E의 PE4 - PE7번(이 Pin을 Input Port(Pin)으로 사용 하는 경우에만 External Interrupt 신호를 입력 받는 Pin으로 사용 할 수 있다.) Pin을 사용 한다. 이 Pin은 표와 같이 해당 Port가 Input Port로 사용 되지 않는 경우 다른 장치들이 사용 할 수 있다.
Interrupt 0(PD0)를 사용 하기 위한 초기화 프로그램 예
External Interrupt 0번 - 3번의 Interrupt Sensing Mode를 설정 한다.
External Interrupt 4번 - 7번의 Interrupt Sensing Mode를 설정 한다.
펄스 신호의 4가지 상태
외부 장치로 부터 발생하는 Hardware Interrupt는 번호로 구분되기 때문에 외부 장치에 의하여 Interrupt가 발생하면 이 번호를 이용하여 Interrupt Service Routine을 실행할 수 있도록 하기 위하여, Interrupt 번호에 대응하는 위치에 Interrupt Service Routine으로 Jmp 하는 명령을 정리한 Table(Interrupt Vector Table)이 필요하다. ATmega128에서 이 Table은 프로그램 메모리 0번 부터 배치된다.
AVR Assembler는 Interrupt Vector Table를 자동으로 생생하지 않기 때문에 아래와 같이 프로그램 작성자가 Interrupt Vector Table을 작성하고 Interrupt Vector를 설정하여야 한다.
GCC Assembler는 GCC 환경에서 사용되는 다른 언어(예: c 언어)와 호환성을 고려 한 Assembler 이기 때문에 프로그램 실행에 필요한 기본 설정(Interrupt Vector Table 생성 등)을 GCC Compiler 가 수행하기 때문에 프로그램 작성자가 별도로 Interrupt Vector Table을 작성할 필요가 없다.
WinAVR GCC Assembly 프로그램에서는 Interrupt Vector 이름(GCC에서 미리 정의한 고유한 이름을 사용하여야함)을 Global 변수로 선언 하면 GCC Compiler 가 Interrupt Vector Table에 자동으로 Interrupt Service Routine의 시작 번지를 설정 한다.
Push Button Switch로 부터 입력되는 신호를 LED Bar에 2진수로 출력 하는 실험 구성도
주: Debouncing를 기능이 없기 때문에 Push button switch(PD0)를 한번 눌러도 경우에 때라 누른 회수가 1 이상 증가하는 경우가 발생한다.