PCINTn 인터럽트를 트리거 한 핀을 결정합니까?


9

동일한 AVR PCINT 인터럽트를 유발하는 두 개의 핀이있는 경우 (예 : PCINT0 또는 PCINT1 핀으로 인한 PCINT0 벡터 -벡터와 핀의 이름 겹침이 혼동된다고 생각합니다) 어떤 핀을 결정하는 유일한 방법이라고 생각합니다 인터럽트가 각 인터럽트 후 상태를 기록하고 PCMSKn에서 활성화 된 모든 핀의 이전 및 현재 값을 비교하는 원인이 되었습니까?


1
AVR을 사용한 지 얼마되지 않았지만 올바른 핀에 트리거되는 플래그가 있어야합니다. 이 플래그는 인터럽트가 발생한 후 지워 지므로 상태를 저장할 필요가 없습니다. 플래그가 충분해야 설정되어 있다는 사실
구스타보 Litovsky

@ gl3829 올바르게 이해하고 있다면 플래그는 핀의 그룹당입니다.
Tom Davies

답변:


11

벡터와 핀의 이름이 겹치는 것은 혼란 스럽다고 생각합니다.

그것은!

인터럽트 벡터에 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
    ...
}

따라서 pins0x01 이면 PB0이라는 것을 알 수 있습니다. 그리고 무엇이 바뀌 었는지 알아야 할 경우에는이를 previousPins정확히 비교해야합니다 .

경우에 pins따라 인터럽트 이후 핀이 상태를 변경하면 핀이 정확하지 않을 수 있습니다.pins = (PINB & 0x03) .

또 다른 옵션은 각 벡터에서 하나의 핀으로 별도의 인터럽트 벡터를 사용하여 어느 것이 변경되었는지 알 수 있습니다. 다시 말하지만, 이것은 또한 인터럽트 우선 순위와 같은 몇 가지 문제를 가지고 있으며, CPU가 ISR에 들어가면, 글로벌 비트 인터럽트 허가 I-bitSREG당신이 그 것하려는 경우 인터럽트 내에서 설정할 수 있지만, 다른 모든 인터럽트를 사용하지 않도록 삭제됩니다 중첩 된 인터럽트 여야합니다.

자세한 내용 은 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 */
    }
}

메가는 벡터 PCINT [0-2]와 함께 3 개의 핀 변경 인터럽트를 갖지만 이들 각각은 핀 세트에 의해 트리거됩니다. 내 질문은 해당 세트의 핀 중 인터럽트를 일으킨 핀을 구별하는 방법에 관한 것입니다.
Tom Davies

@ TomDavies 당신이 맞습니다. 감사합니다. 내 대답을 변경했지만 정확히 당신이 생각한 것입니다. 그리고 데이터 시트를 읽었으며 핀이 변경된 것을 나타내는 플래그가 없습니다.
Garrett Fogerlie

@ Garret : 원래 예제에서 인터럽트를 발생시킨 것이 상승 에지인지 상승 에지인지 쉽게 알 수 있다는 것을 알고 계셨습니까? (음, 두 핀이 정확히 같은 순간에 변경되지 않는 한 ...하지만이 경우 블랙 매직 만 도움이됩니다) (previous_pins> pins) : 떨어지는 가장자리 (이전 핀 <핀) : 상승 가장자리 아마도 위에서 언급 할 가치가 있습니다.

@TomDavies PINB는 PCINT0-7을 커버하고, PINC는 PCINT8-15를 커버합니다
EkriirkE

0

최신 ATTINY 시리즈 INTFLAGS레지스터에서 인터럽트를 일으킨 포트 비트를 알려줍니다.

다음은 데이터 시트에서 발췌 한 내용입니다.

비트 7 : 0 – INT [7 : 0] : 인터럽트 핀 플래그 INT 플래그는 핀 변경 / 상태가 핀의 입력 감지 구성과 일치 할 때 설정됩니다. 플래그의 비트 위치에 '1'을 쓰면 플래그가 지워집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.