동일한 AVR PCINT 인터럽트를 유발하는 두 개의 핀이있는 경우 (예 : PCINT0 또는 PCINT1 핀으로 인한 PCINT0 벡터 -벡터와 핀의 이름 겹침이 혼동된다고 생각합니다) 어떤 핀을 결정하는 유일한 방법이라고 생각합니다 인터럽트가 각 인터럽트 후 상태를 기록하고 PCMSKn에서 활성화 된 모든 핀의 이전 및 현재 값을 비교하는 원인이 되었습니까?
동일한 AVR PCINT 인터럽트를 유발하는 두 개의 핀이있는 경우 (예 : PCINT0 또는 PCINT1 핀으로 인한 PCINT0 벡터 -벡터와 핀의 이름 겹침이 혼동된다고 생각합니다) 어떤 핀을 결정하는 유일한 방법이라고 생각합니다 인터럽트가 각 인터럽트 후 상태를 기록하고 PCMSKn에서 활성화 된 모든 핀의 이전 및 현재 값을 비교하는 원인이 되었습니까?
답변:
벡터와 핀의 이름이 겹치는 것은 혼란 스럽다고 생각합니다.
그것은!
인터럽트 벡터에 8 개의 서로 다른 외부 핀이있는 이유는 다른 핀 기능과 충돌이있을 경우 PCB를보다 쉽게 레이아웃하거나 다른 핀을 사용하기 때문입니다.
어떤 인터럽트가 인터럽트를 유발했는지를 결정하는 유일한 방법은 각 인터럽트 후 상태를 기록하고 PCMSKn에서 활성화 된 모든 핀의 이전 및 현재 값을 비교하는 것입니다.
PB0 (PCINT0)과 PB1 (PCINT1)에 대해서만 신경을 쓰면됩니다. 따라서 핀 변경 활성화 마스크 PCMSK0은 0x03으로 설정됩니다.
// External Interrupt Setup
...
volatile u_int8 previousPins = 0;
volatile u_int8 pins = 0;
ISR(SIG_PIN_CHANGE0)
{
previousPins = pins; // Save the previous state so you can tell what changed
pins = (PINB & 0x03); // set pins to the value of PB0 and PB1
...
}
따라서 pins
0x01 이면 PB0이라는 것을 알 수 있습니다. 그리고 무엇이 바뀌 었는지 알아야 할 경우에는이를 previousPins
정확히 비교해야합니다 .
경우에 pins
따라 인터럽트 이후 핀이 상태를 변경하면 핀이 정확하지 않을 수 있습니다.pins = (PINB & 0x03)
.
또 다른 옵션은 각 벡터에서 하나의 핀으로 별도의 인터럽트 벡터를 사용하여 어느 것이 변경되었는지 알 수 있습니다. 다시 말하지만, 이것은 또한 인터럽트 우선 순위와 같은 몇 가지 문제를 가지고 있으며, CPU가 ISR에 들어가면, 글로벌 비트 인터럽트 허가 I-bit
에 SREG
당신이 그 것하려는 경우 인터럽트 내에서 설정할 수 있지만, 다른 모든 인터럽트를 사용하지 않도록 삭제됩니다 중첩 된 인터럽트 여야합니다.
자세한 내용 은 megaAVR 장치 에 Atmel의 앱 노트 Using External Interrupts를 참조하십시오.
최신 정보
여기에 방금 찾은 완전한 코드 예제가 있습니다 .
#include <avr/io.h>
#include <stdint.h> // has to be added to use uint8_t
#include <avr/interrupt.h> // Needed to use interrupts
volatile uint8_t portbhistory = 0xFF; // default is high because the pull-up
int main(void)
{
DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2)); // Clear the PB0, PB1, PB2 pin
// PB0,PB1,PB2 (PCINT0, PCINT1, PCINT2 pin) are now inputs
PORTB |= ((1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2)); // turn On the Pull-up
// PB0, PB1 and PB2 are now inputs with pull-up enabled
PCICR |= (1 << PCIE0); // set PCIE0 to enable PCMSK0 scan
PCMSK0 |= (1 << PCINT0); // set PCINT0 to trigger an interrupt on state change
sei(); // turn on interrupts
while(1)
{
/*main program loop here */
}
}
ISR (PCINT0_vect)
{
uint8_t changedbits;
changedbits = PINB ^ portbhistory;
portbhistory = PINB;
if(changedbits & (1 << PB0))
{
/* PCINT0 changed */
}
if(changedbits & (1 << PB1))
{
/* PCINT1 changed */
}
if(changedbits & (1 << PB2))
{
/* PCINT2 changed */
}
}