Menentukan pin mana yang memicu interupsi PCINTn?

9

Apakah saya benar dalam berpikir bahwa jika Anda memiliki dua pin yang menyebabkan interupsi AVR PCINT yang sama, (misalnya vektor PCINT0 disebabkan oleh pin PCINT0 atau PCINT1 - Saya pikir penamaan yang tumpang tindih antara vektor dan pin membingungkan) satu-satunya cara untuk menentukan pin mana (s) menyebabkan interupsi untuk merekam keadaan mereka setelah setiap interupsi dan membandingkan nilai sebelumnya dan saat ini dari semua pin yang diaktifkan di PCMSKn?

Tom Davies
sumber
1
Sudah lama sejak saya menggunakan AVR, tapi saya yakin harus ada bendera yang dipicu untuk pin yang tepat. Bendera ini harus dihapus setelah interupsi terjadi, sehingga Anda tidak perlu menyimpan status. Fakta bahwa bendera ditetapkan harus cukup
Gustavo Litovsky
@ gl3829 bendera adalah per kelompok pin jika saya mengerti dengan benar
Tom Davies

Jawaban:

11

Saya pikir penamaan yang tumpang tindih antara vektor dan pin membingungkan

Ini!

Alasannya ada 8 pin eksternal yang berbeda untuk vektor interupsi adalah untuk memudahkan tata letak PCB atau menggunakan pin yang berbeda jika ada konflik dengan fungsi pin lainnya.

Apakah saya benar dalam berpikir ... satu-satunya cara untuk menentukan pin mana yang menyebabkan interupsi adalah mencatat keadaan mereka setelah setiap interupsi dan membandingkan nilai sebelumnya dan saat ini dari semua pin yang diaktifkan di PCMSKn?

Cukup banyak, katakanlah Anda hanya peduli tentang PB0 (PCINT0) dan PB1 (PCINT1). Jadi perubahan pin memungkinkan mask PCMSK0 akan diatur ke 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
    ...
}

Jadi jika pins0x01 Anda tahu itu PB0 ... Dan jika Anda perlu tahu apa yang berubah, Anda perlu membandingkannya previousPins, persis seperti yang Anda pikirkan.

Perlu diingat dalam beberapa kasus, pinsmungkin tidak akurat jika pin telah berubah sejak interupsi tetapi sebelumnya pins = (PINB & 0x03).

Pilihan lain adalah menggunakan vektor interupsi terpisah dengan satu pin dari masing-masing vektor sehingga Anda tahu mana yang diubah. Sekali lagi, ini juga memiliki beberapa masalah, seperti prioritas interupsi dan sekali CPU memasuki ISR, global interrupt mengaktifkan bit I-bitdi SREGakan dihapus sehingga semua interupsi lainnya dinonaktifkan, meskipun Anda dapat mengaturnya di dalam interupsi jika Anda inginkan, yang akan menjadi interupsi bersarang.

Untuk informasi lebih lanjut, lihat catatan aplikasi Atmel Menggunakan Interupsi Eksternal untuk Perangkat megaAVR.

Memperbarui

Ini adalah contoh kode lengkap yang baru saya temukan di sini .

#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 */
    }
}
Garrett Fogerlie
sumber
Mega memiliki tiga interupsi perubahan pin, dengan vektor PCINT [0-2], tetapi masing-masing dipicu oleh satu set pin. Pertanyaan saya adalah tentang bagaimana membedakan pin mana yang menyebabkan interupsi.
Tom Davies
@ TomDavies Anda benar, terima kasih, saya mengubah jawaban saya namun itulah yang Anda pikirkan. Dan saya membaca datasheet, tidak ada bendera untuk menunjukkan pin apa yang berubah.
Garrett Fogerlie
@ Garret: Apakah Anda mengenali bahwa dalam contoh asli Anda, seseorang dapat dengan mudah menentukan apakah itu jatuh atau naiknya tepi yang memicu interupsi? (baik, kecuali kedua pin berubah pada saat yang sama persis ... tetapi dalam kasus ini hanya ilmu hitam yang membantu) (prior_pins> pin): ujung jatuh (pin sebelumnya <pin): tepi naik Mungkin ini layak disebutkan di atas.
@TomDavies PINB mencakup PCINT0-7, PINC mencakup PCINT8-15 dll
EkriirkE
0

Pada seri ATTINY INTFLAGSregister yang lebih baru akan memberi tahu Anda apa bit port yang menyebabkan interupsi.

Berikut ini kutipan dari datasheet:

Bits 7: 0 - INT [7: 0]: Flag Pin Interrupt Bendera INT diatur ketika pin berganti / menyatakan cocok dengan konfigurasi indra input pin. Menulis '1' ke lokasi bit bendera akan menghapus bendera.

zmekanik
sumber