PCINTn割り込みをトリガーしたピンを特定するには?


9

同じAVR PCINT割り込みを引き起こす2つのピンがある場合(たとえば、PCINT0またはPCINT1ピンによって引き起こされるPCINT0 ベクトル -ベクトルとピンの名前の重複が混乱していると思います)、どのピンを決定する唯一の方法だと思いますか? (s)割り込みが原因で、各割り込みの後に状態が記録され、PCMSKnで有効になっているすべてのピンの以前の値と現在の値が比較されますか?


1
AVRを使用して久しぶりですが、正しいピンに対してトリガーされるフラグがあるはずです。このフラグは、割り込みが発生した後にクリアされるため、状態を保存する必要はありません。フラグが設定されているという事実で十分です
Gustavo 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)

別のオプションは、各ベクトルから1つのピンを持つ個別の割り込みベクトルを使用して、どれが変更されたかを知ることです。繰り返しますが、これはまた、割り込み優先順位のようないくつかの問題を、持っていると、CPUはISRに入ると、グローバル割り込みイネーブルビットI-bitSREGしたい場合は、割り込みの内側にそれを設定することができますがあろうと、他のすべての割り込みが無効になっているようにクリアされます入れ子の割り込みであること。

詳細については、Atmelのアプリケーションノート「megaAVRデバイスの外部割り込みの使用」を参照してください

更新

ここに私がここで見つけた完全なコード例があります

#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つのピン変更割り込みがありますが、それらはそれぞれピンのセットによってトリガーされます。私の質問は、そのセットのどのピンが割り込みを引き起こしたかを区別する方法についてです。
トムデイビス

@TomDaviesあなたは正しいです、ありがとう、私は私の答えを変更しましたが、それはまさにあなたが考えたことです。データシートを読みましたが、どのピンが変更されたかを示すフラグはありません。
Garrett Fogerlie、

@ Garret:元の例では、割り込みをトリガーしたのが立ち下がりエッジか立ち上がりエッジかを簡単に判断できることをご存知ですか?(まあ、両方のピンが正確に同時に変更されない限り...ただし、この場合は黒魔術だけが役立ちます)(previous_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.