Arduino Uno R3에서 7 채널 RC 수신기를 사용하려고합니다. 문서에는 최대 2 개의 인터럽트 핀에 대한 언급이 있지만 다른 특정 블로그에서는 PinChangeInt 라이브러리와 함께 최대 20 개의 핀을 인터럽트로 사용하는 것에 대한 언급을 보았습니다. 그렇다면 Arduino는 기본적으로 얼마나 많은 인터럽트를 처리 할 수 있습니까? 그리고 이것은 PinChangeInt와 같은 소프트웨어 지원으로 처리 할 수있는 수와 다른가요?
Answer
“에는 두 가지 유형이 있습니다. 핀 변경 “유형 인터럽트. Uno에 2 개가있는 외부 인터럽트. 0과 1이라고하지만 보드의 디지털 핀 2와 3을 참조합니다. 상승, 하락, 변화 (상승 또는 하락) 또는 LOW를 감지하도록 구성 할 수 있습니다.
그 외에도 20 개 핀 (A0 ~ A5, D0 ~ D13)에서 핀 상태의 변화를 감지하는 “핀 변경”인터럽트가 있습니다. 이러한 핀 변경 인터럽트도 하드웨어 기반 이므로 그 자체로 외부 인터럽트만큼 빠릅니다.
두 유형 모두 레지스터 수준에서 사용하기에는 약간 까다 롭지 만 표준 IDE에는 외부 인터럽트에 대한 인터페이스를 단순화하는 attachInterrupt (n) 및 detachInterrupt (n)이 포함되어 있습니다. 핀 변경 라이브러리 를 사용하여 핀 변경 인터럽트를 단순화 할 수도 있습니다.
그러나 잠시 동안 라이브러리에서 벗어나면됩니다. 핀 변경 인터럽트가 외부 인터럽트보다 빠르거나 빠를 수 있음을 확인할 수 있습니다. 우선, 핀 변경 인터럽트가 핀 배치에서 작동하지만 전체 배치를 활성화 할 필요는 없습니다. 예를 들어 핀 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 () { }
내 테스트에 따르면 “테스트에 1.6µs가 걸렸습니다. “핀 (핀 5)은 인터럽트 핀 (핀 4)의 변경에 반응합니다.
이제 간단한 (게으른?) 접근 방식을 사용하고 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에서 가장 빠른 것입니다. 하나의 클럭 사이클이 어딘가에 저장되어있는 것처럼 보입니다.
핀 변경 인터럽트에 대한 한 가지주의 사항이 있습니다. 일괄 처리되므로 많은 핀에서 인터럽트를 사용하려면 인터럽트 내부에서 테스트해야합니다. . 이전 핀 상태를 저장하고 새 핀 상태와 비교하여이를 수행 할 수 있습니다. 이것은 반드시 특별히 느린 것은 아니지만 확인해야하는 핀이 많을수록 속도가 느려집니다.
배치 :
- A0 ~ A5
- D0 ~ D7
- D8 ~ D13
인터럽트 핀을 몇 개 더 원할 경우 다른 핀을 사용하도록 선택하여 테스트를 피할 수 있습니다. 배치 (예 : D4 및 D8).
자세한 내용은 http://www.gammon.com.au/interrupts 를 참조하세요.
답변
두 가지 유형의 인터럽트가 있습니다. Arduino Playground 의 말 :
Arduino의 핵심 프로세서에는 “외부”와 “핀 변경”이라는 두 가지 종류의 인터럽트가 있습니다. ATmega168 / 328 (예 : Arduino Uno / Nano / Duemilanove), INT0 및 INT1에는 두 개의 외부 인터럽트 핀만 있으며 Arduino 핀 2 및 3에 매핑됩니다. 이러한 인터럽트는 RISING 또는 FALLING 신호 에지 또는 로우 레벨. 트리거는 하드웨어에 의해 해석되며 인터럽트는 매우 빠릅니다. Arduino Mega에는 사용 가능한 외부 인터럽트 핀이 몇 개 더 있습니다.
반면에 핀 변경 인터럽트는 더 많은 핀에서 활성화 할 수 있습니다. ATmega168 / 328 기반 Arduino의 경우 Arduino의 신호 핀 20 개 중 일부 또는 전부에서 활성화 할 수 있습니다. ATmega 기반 Arduino에서는 24 핀에서 활성화 할 수 있습니다. 이들은 RISING 또는 FALLING 신호 에지에서 동일하게 트리거됩니다. 따라서 인터럽트를 수신하기위한 적절한 핀을 설정하고, 무슨 일이 발생했는지 (어떤 핀? … 신호가 상승 또는 하강 했습니까?), 적절하게 처리하는 것은 인터럽트 코드에 달려 있습니다.또한 핀 변경 인터럽트는 MCU에서 3 개의 “포트”로 그룹화되므로 전체 핀 바디에 대해 3 개의 인터럽트 벡터 (서브 루틴) 만 있습니다. 따라서 단일 인터럽트에 대한 작업을 해결하는 작업이 훨씬 더 복잡해집니다.
기본적으로 외부 인터럽트는 모두 하드웨어 기반이므로 매우 빠릅니다. . 그러나 핀 변경 인터럽트도 있지만 대부분 소프트웨어 기반이기 때문에 훨씬 느린 것 같습니다.
tl; dr : 20 개의 인터럽트 핀을 함께 사용하면 훨씬 느립니다. 2 개의 인터럽트 핀이 가장 빠르고 효율적입니다.
편집 : 방금 데이터 시트를 봤는데 표시없이 선택한 핀 모든 에 대해 핀 변경 인터럽트가 트리거되었다고합니다. 어느 핀이 변경되었는지 (3 개의 인터럽트 벡터로 분할되어 있음)
- 외부 인터럽트의 경우 “핀 3이 방금 변경됨
- 핀 변경의 경우 “모니터링중인 핀이 변경되었습니다!
보시다시피 핀 변경 인터럽트는 이전 상태를 저장하고 걱정되는 핀인지 확인하여 처리해야하는 ISR에 많은 오버 헤드를 추가합니다. 휴면 상태에서는 괜찮을 수 있지만 외부 인터럽트를 사용하는 것이 좋습니다.