답변:
"핀 변경"유형 인터럽트에는 두 가지 유형이 있습니다. Uno에 2 개의 외부 인터럽트가 있습니다. 그것들은 0과 1이라고 불리지 만 보드의 디지털 핀 2와 3을 가리 킵니다. 이들은 상승, 하강, 변화 (상승 또는 하강) 또는 LOW 를 감지하도록 구성 할 수 있습니다 .
그 외에도 20 개의 핀 (A0 ~ A5 및 D0 ~ D13)에서 핀 상태 변경을 감지하는 "핀 변경"인터럽트가 있습니다. 이 핀 변경 인터럽트는 하드웨어 기반 이므로 외부 인터럽트만큼 빠릅니다.
두 가지 유형 모두 레지스터 수준에서 약간 사용하기 쉽지만 표준 IDE에는 attachInterrupt (n) 및 detachInterrupt (n)이 포함되어있어 외부 인터럽트 인터페이스를 단순화합니다. 핀 변경 라이브러리 를 사용하여 핀 변경 인터럽트를 단순화 할 수도 있습니다 .
그러나 1 분 동안 라이브러리에서 벗어나면 핀 변경 인터럽트가 외부 인터럽트보다 빠르거나 빠를 수 있습니다. 우선 핀 배치 인터럽트가 핀 배치에서 작동하지만 전체 배치를 활성화 할 필요는 없습니다. 예를 들어, D4 핀의 변경 사항을 감지하려면 다음과 같이 충분합니다.
스케치 예 :
ISR (PCINT2_vect)
{
// handle pin change interrupt for D0 to D7 here
if (PIND & bit (4)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of PCINT2_vect
void setup ()
{
// pin change interrupt (example for D4)
PCMSK2 |= bit (PCINT20); // want pin 4
PCIFR |= bit (PCIF2); // clear any outstanding interrupts
PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7
pinMode (4, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
필자의 테스트에 따르면 "테스트"핀 (핀 5)이 인터럽트 핀 (핀 4)의 변화에 반응하는 데 1.6µs가 걸린 것으로 나타났습니다.
이제 간단한 (lazy?) 접근 방식을 사용하고 attachInterrupt ()를 사용하면 결과가 더 빠르지 않고 느리다는 것을 알 수 있습니다.
예제 코드 :
void myInterrupt ()
{
if (PIND & bit (2)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of myInterrupt
void setup ()
{
attachInterrupt (0, myInterrupt, CHANGE);
pinMode (2, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
테스트 핀을 교체하는 데 3.7µs가 걸리며, 이는 1.6µs보다 훨씬 높습니다. 왜? 컴파일러가 "일반적인"인터럽트 핸들러에 대해 생성해야하는 코드는 ISR에 진입 할 때 모든 가능한 레지스터를 저장 한 다음 (누르고) 반환하기 전에 복원해야합니다. 또한 다른 함수 호출의 오버 헤드가 있습니다.
이제 우리는 attachInterrupt ()를 피하고 스스로 수행함으로써 그 문제를 해결할 수 있습니다.
ISR (INT0_vect)
{
if (PIND & bit (2)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of INT0_vect
void setup ()
{
// activate external interrupt 0
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags
EICRA |= bit (ISC00); // set wanted flags (any change interrupt)
EIFR = bit (INTF0); // clear flag for interrupt 0
EIMSK |= bit (INT0); // enable it
pinMode (2, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
이는 1.52 µs에서 가장 빠릅니다. 한 클럭 사이클이 어딘가에 저장된 것처럼 보입니다.
그래도 핀 변경 인터럽트에는 한 가지주의 사항이 있습니다. 일괄 처리되므로 많은 핀에 인터럽트 를 적용 하려면 인터럽트 내부에서 변경된 핀을 테스트해야합니다 . 이전 핀 상태를 저장하고이를 새 핀 상태와 비교하면됩니다. 반드시 느릴 필요는 없지만 확인할 핀이 많을수록 느려집니다.
배치는 다음과 같습니다.
인터럽트 핀을 몇 개 더 원하는 경우 다른 배치 (예 : D4 및 D8)의 핀을 사용하도록 선택하면 테스트를 피할 수 있습니다.
인터럽트에는 두 가지 유형이 있습니다. 무엇 아두 이노 운동장은 말했다 :
Arduino의 핵심 프로세서에는 "외부"및 "핀 변경"이라는 두 가지 종류의 인터럽트가 있습니다. ATmega168 / 328 (예 : Arduino Uno / Nano / Duemilanove), INT0 및 INT1에는 2 개의 외부 인터럽트 핀만 있으며 Arduino 핀 2 및 3에 매핑됩니다. 이러한 인터럽트는 RISING 또는 트리거시 트리거되도록 설정할 수 있습니다. 하강 신호 에지 또는 로우 레벨. 트리거는 하드웨어에 의해 해석되며 인터럽트는 매우 빠릅니다. Arduino Mega에는 몇 가지 외부 인터럽트 핀이 있습니다.
반면 핀 변경 인터럽트는 더 많은 핀에서 활성화 될 수 있습니다. ATmega168 / 328 기반 Arduino의 경우 Arduino의 신호 핀 중 일부 또는 모두에서 활성화 할 수 있습니다. ATmega 기반 Arduino의 경우 24 핀에서 활성화 할 수 있습니다. RISING 또는 FALLING 신호 에지에서 동일하게 트리거되므로 인터럽트를 수신 할 적절한 핀을 설정하고 어떤 핀이 발생했는지 (신호 핀이 상승 또는 하강 했는가) 결정하는 것은 인터럽트 코드에 달려 있습니다. 제대로 처리합니다. 또한 핀 변경 인터럽트는 MCU에서 3 개의 "포트"로 그룹화되므로 전체 핀 바디에 대해 3 개의 인터럽트 벡터 (서브 루틴) 만 있습니다. 이를 통해 단일 인터럽트에 대한 조치를 해결하는 작업이 훨씬 더 복잡해집니다.
기본적으로 외부 인터럽트는 모두 하드웨어 기반이기 때문에 매우 빠릅니다. 그러나 핀 변경 인터럽트도 있지만 소프트웨어 기반이기 때문에 속도가 훨씬 느려 보입니다.
tl; dr : 20 개의 인터럽트 핀이 함께 훨씬 느립니다. 2 개의 인터럽트 핀이 가장 빠르고 효율적입니다.
편집 : 방금 데이터 시트를 보았고 어떤 핀이 변경되었는지 표시하지 않고 선택한 핀 중 하나 에 대해 핀 변경 인터럽트가 트리거된다고 말합니다 (3 개의 인터럽트 벡터로 나뉘어 있음).
보다시피, 핀 변경 인터럽트는 이전 상태를 저장하고 걱정되는 핀인지 확인하여 처리해야하는 ISR에 많은 오버 헤드를 추가합니다. 수면 상태에는 문제가 없지만 외부 인터럽트를 사용하는 것이 좋습니다.