※ AVR-gcc 에서 interrupt.h 파일의 매크로(디파인) 들을 이용해서 핸들러 등록하는 방법입니다. |
AVR 인터럽트 핸들링
- ISR() 매크로를 이용해서 핸들러 작성 ( avr-libc 1.4.0 부터, 이전의 SIG_ 스타일은 폐기 )
#include <avr/interrupt.h>
ISR(ADC_vect)
{
// user code here
}
- XXXX_vect : datasheet에 기록된 인터럽트 이름에서 공백은 '_'로 바뀌고 알파벳, 숫자가 아닌 것
은 삭제하여 인터럽트 이름이 만들어 졌다. (avr-libc 매뉴얼 참조)
※ 모든 인터럽트 잡기
- 처리 코드가 제공되지 않은 인터럽트가 발생하면 기본 동작은 장치를 리셋하는 것이다.
- 이러한 인터럽트를 처리하기 위한 코드의 제공은 ISR(BADISR_vect)를 이용한다.
#include <avr/interrupt.h>
ISR(BADISR_vect)
{
// user code here
}
※ 중첩된 인터럽트의 처리
- AVR은 인터럽트 루틴으로 들어가기 전에 SREG의 전역인터럽트 플래그를 소거하여 인터럽트의
다른 발생을 금지한다. 따라서, 인터럽트 처리는 보통 중첩되지 않고 이것이 바람직 하다.
- 드문 경우지만 한 인터럽트 처리루틴 내에서 처리도중 꼭 필요한 다른 인터럽트를 처리해야 할
필요가 있는 경우에는 핸들러의 맨 처음 시작 부분에 sei()를 이용해서 다른 인터럽트를 허용해야
한다. 하지만 C 컴파일러가 생성한 코드가 유저가 제공한 코드 앞에 들어간다.
- ISR_NOBLOCK라는 매크로를 이용해서 핸들러를 이용하면 컴파일러가 sei()를 핸들러 맨 처음에
삽입해 준다.
ISR(XXX_vect, ISR_NOBLOCK)
{
// user code here
}
※ 같은 코드를 공유하는 인터럽트
- 서로 다른 인터럽트가 동일한 코드를 수행한다면 ISR_ALIASOF() 속성을 이용한다.
ISR(PCINT0_vect)
{
...
// Code to handle the event.
}
ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));
- 별명으로 처리된 인터럽트는 코드를 가지지 않는다.
※ 빈 인터럽트 처리 루틴
- 핸들러에서 아무일도 하지 않는 인터럽트를 만들고 이것이 기본처리되는 인터럽트가 아니라면
EMPTY_INTERRUPT() 매크로를 이용하여 선언한다.
- 이러한 인터럽트의 예로는 SLEEP 모드에서 빠져 나오는 용도가 있다.
EMPTY_INTERRUPT(ADC_vect);
※ ISR을 직접 작성
- 컴파일러에서 제공되는 코드를 포함하는 인터럽트 루틴은 최적화 되지 않을 수 있으므로,
인터럽트 처리 속도를 빠르게 하기 위해서 ISR의 전체루틴을 직접 만들어서 제공할 수 있다.
- 하나의 방법은 어셈블리를 이용해서 독립된 파일로 만들어서 컴파일 하는 방법 이다.
- C 언어 상에서 ISR 전체 루틴을 제공하고 싶다면 ISR_NAKED라는 매크로를 사용한다.
ISR(TIMER1_OVF_vect, ISR_NAKED)
{
PORTB |= _BV(0); // results in SBI which does not affect SREG
reti();
}
- 주의할 점은 SREG의 값이 변경되면 이를 복구해야하고, 마지막에 reti()를 반드시 호출해야 한다.
'코스웨어 > 13년 스마트컨트롤러' 카테고리의 다른 글
<11일 정리> AVR로 초음파 센서 값 LCD로 출력하기 - 문예진 (4) | 2013.06.11 |
---|---|
[AVR 보고서용 main소스입니다] by. 남경 (0) | 2013.06.11 |
뉴스 기사보다가 정말 획기적인 기사가 떠서.. (3) | 2013.06.10 |
6월 10일 정리 - 문예진 (2) | 2013.06.10 |
6월 7일 금요일 정리 조유진 (2) | 2013.06.07 |
놀땐 미친듯이 놀아야지 ㅋㅋㅋㅋㅋㅋ (3) | 2013.06.06 |
도서관리 최종 (7) | 2013.06.06 |
초음파 센서하니 떠오른...음속에 대해 - 전영기 (4) | 2013.06.05 |