Hangi iğnenin PCINTn kesmesini tetiklediğini belirleme


9

Aynı AVR PCINT kesmesine neden olan iki piminiz varsa (örneğin, PCINT0 veya PCINT1 pimlerinden kaynaklanan PCINT0 vektörü - Bence vektörlerin ve pimlerin adlandırma örtüşmesinin kafa karıştırıcı olduğunu düşünüyorum) tek pimi belirlemenin tek yolu kesme her durumdan sonra kendi durumlarını kaydetmek ve PCMSKn etkinleştirilen tüm pimlerin önceki ve geçerli değerleri karşılaştırmak neden?


1
Bir AVR kullandığımdan bu yana bir süre geçti, ancak eminim doğru pim için tetiklenen bir bayrak olmalı. Kesinti meydana geldikten sonra bu işaretin temizlenmesi gerekir, böylece durumu depolamanız gerekmez. Bayrağın ayarlanmış olması yeterli olmalı
Gustavo Litovsky

@ gl3829 Eğer doğru anlıyorsam bayrak pim grubu başına
Tom Davies

Yanıtlar:


11

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 pins0x01 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, pinspimin 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-bitiçinde SREGsen, 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 */
    }
}

Mega, PCINT [0-2] vektörleri ile üç pim değiştirme kesintisine sahiptir, ancak bunların her biri bir dizi pim tarafından tetiklenir. Benim sorum, o setteki pimlerin hangisinin kesintiye neden olduğunu ayırt etmekle ilgili.
Tom Davies

@TomDavies haklısın, teşekkürler, cevabımı değiştirdim ancak tam olarak düşündüğün buydu. Ve veri sayfasını okudum, hangi pimin değiştiğini gösteren bir bayrak yok.
Garrett Fogerlie

@ Garret: Orijinal örneğinizde, kesmeyi tetikleyen düşen veya yükselen kenar olup olmadığını kolayca belirleyebildiniz mi? (her iki pim de aynı anda değişmedikçe ... ancak bu durumda sadece kara büyü yardımcı olur) (önceki_pin> pimler): düşen kenar (önceki pimler <pimler): yükselen kenar Belki de yukarıda belirtilmeye değer.

@TomDavies PINB PCINT0-7, PINC PCINT8-15 vb.
Kapsar

0

Yeni ATTINY serisi INTFLAGSkayıt defterinde kesintiye hangi port bitinin neden olduğu söylenecektir.

Veri sayfasından alıntı:

Bit 7: 0 - INT [7: 0]: Kesme Pim Bayrak bir iğne değişim / devlet iğnelerin giriş duyu yapılandırmasını eşleştiğinde INT Bayrak ayarlanır. Bir bayrağın bit konumuna bir '1' yazılması bayrağın temizlenmesine neden olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.