Vektörlerin ve iğnelerin adlandırma örtüşmesinin kafa karıştırıcı olduğunu düşünüyorum
Bu!
Bir kesme vektörü için 8 farklı harici pim olmasının nedeni PCB'yi düzenlemeyi kolaylaştırmak veya başka bir pim işleviyle çakışma olması durumunda farklı bir pim kullanmaktır.
Düşünmede doğru muyum? Kesmeye hangi pin (ler) in neden olduğunu belirlemenin tek yolu, her kesmeden sonra durumlarını kaydetmek ve PCMSKn'de etkin olan tüm pinlerin önceki ve geçerli değerlerini karşılaştırmaktır?
Hemen hemen sadece PB0 (PCINT0) ve PB1 (PCINT1) değerlerini önemsediğinizi varsayalım. Bu nedenle, pin değiştirme etkinleştirme maskesi PCMSK0 0x03 olarak ayarlanacaktır.
// 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
...
}
Yani pins
0x01 ise , bunun PB0 olduğunu biliyorsunuz ... Ve neyin değiştiğini bilmeniz gerekiyorsa, karşılaştırmak zorundasınız previousPins
, tam olarak düşündüğünüz şey.
Bazı durumlarda, pins
pimin kesilmeden beri fakat daha önce durum değiştirmesi durumunda doğru olmayabilir pins = (PINB & 0x03)
.
Başka bir seçenek, her bir vektörden bir pim ile ayrı kesinti vektörleri kullanmaktır, böylece hangisinin değiştiğini bilirsiniz. Yine, bu da kesme öncelik gibi bazı sorunlar vardır ve CPU ISR girdiğinde, küresel bit etkinleştirmek kesme I-bit
içinde SREG
sen, o olur istiyorsanız kesme içine ayarlayabilirsiniz rağmen, diğer tüm kesilmeler saf dışı bırakılır böylece silinecektir yuvalanmış bir kesinti olmak.
Daha fazla bilgi için Atmel'in megaAVR Cihazları için Harici Kesintileri Kullanma uygulama notuna bakın.
Güncelleme
İşte burada bulduğum tam bir kod örneği .
#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 */
}
}