同じAVR PCINT割り込みを引き起こす2つのピンがある場合(たとえば、PCINT0またはPCINT1ピンによって引き起こされるPCINT0 ベクトル -ベクトルとピンの名前の重複が混乱していると思います)、どのピンを決定する唯一の方法だと思いますか? (s)割り込みが原因で、各割り込みの後に状態が記録され、PCMSKnで有効になっているすべてのピンの以前の値と現在の値が比較されますか?
同じAVR PCINT割り込みを引き起こす2つのピンがある場合(たとえば、PCINT0またはPCINT1ピンによって引き起こされるPCINT0 ベクトル -ベクトルとピンの名前の重複が混乱していると思います)、どのピンを決定する唯一の方法だと思いますか? (s)割り込みが原因で、各割り込みの後に状態が記録され、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)
。
別のオプションは、各ベクトルから1つのピンを持つ個別の割り込みベクトルを使用して、どれが変更されたかを知ることです。繰り返しますが、これはまた、割り込み優先順位のようないくつかの問題を、持っていると、CPUはISRに入ると、グローバル割り込みイネーブルビットI-bit
にSREG
したい場合は、割り込みの内側にそれを設定することができますがあろうと、他のすべての割り込みが無効になっているようにクリアされます入れ子の割り込みであること。
詳細については、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 */
}
}