Berapa banyak pin interupsi yang dapat ditangani oleh Uno?

16

Saya melihat menggunakan penerima RC 7 saluran dengan Arduino Uno R3. Dalam dokumentasi, ada menyebutkan maksimal 2 pin interupsi, sedangkan di blog lain saya telah melihat menyebutkan menggunakan hingga 20 pin sebagai interupsi, dengan perpustakaan PinChangeInt. Jadi, berapa banyak interupsi yang bisa ditangani Arduino secara asli? Dan apakah ini berbeda dari berapa banyak yang dapat ditangani dengan dukungan perangkat lunak seperti PinChangeInt?

asheeshr
sumber

Jawaban:

13

Ada dua jenis interupsi tipe "perubahan pin". Interupsi eksternal, yang ada dua di Uno. Mereka disebut 0 dan 1, namun mereka merujuk pada pin digital 2 dan 3 di papan tulis. Ini dapat dikonfigurasi untuk mendeteksi naik, turun, berubah (naik atau turun) atau RENDAH.

Selain itu, interupsi "perubahan pin", yang mendeteksi perubahan ke status pin di salah satu dari 20 pin (A0 ke A5, dan D0 ke D13). Interupsi penggantian pin ini juga berbasis perangkat keras sehingga, dalam dirinya sendiri, akan secepat interupsi eksternal.

Kedua jenis ini sedikit rumit untuk digunakan pada level register, tetapi IDE standar mencakup attachInterrupt (n) dan detachInterrupt (n) yang menyederhanakan antarmuka ke interupsi eksternal. Anda juga dapat menggunakan Perpustakaan Perubahan Pin untuk menyederhanakan interupsi perubahan pin.

Namun, menjauhi perpustakaan selama satu menit, kita dapat menetapkan bahwa interupsi penggantian pin bisa lebih cepat, atau lebih cepat, daripada interupsi eksternal. Untuk satu hal, meskipun perubahan pin mengganggu bekerja pada batch pin, Anda tidak harus mengaktifkan seluruh batch. Misalnya, jika Anda ingin mendeteksi perubahan pada pin D4, ini sudah cukup:

Contoh sketsa:

ISR (PCINT2_vect)
 {
 // handle pin change interrupt for D0 to D7 here
 if (PIND & bit (4))  // if it was high
   PORTD |= bit (5);  // turn on D5
 else
   PORTD &= ~bit (5); // turn off D5
 }  // end of PCINT2_vect

void setup ()
  { 
  // pin change interrupt (example for D4)
  PCMSK2 |= bit (PCINT20);  // want pin 4
  PCIFR  |= bit (PCIF2);    // clear any outstanding interrupts
  PCICR  |= bit (PCIE2);    // enable pin change interrupts for D0 to D7
  pinMode (4, INPUT_PULLUP);
  pinMode (5, OUTPUT);
  }  // end of setup

void loop ()
  {
  }

Pengujian saya menunjukkan bahwa butuh 1,6 μs untuk pin "test" (pin 5) untuk bereaksi terhadap perubahan pada pin interrupt (pin 4).


Sekarang jika Anda mengambil pendekatan sederhana (malas?) Dan menggunakan attachInterrupt () Anda akan menemukan hasilnya lebih lambat, tidak lebih cepat.

Kode contoh:

void myInterrupt ()
 {
 if (PIND & bit (2))  // if it was high
   PORTD |= bit (5);  // turn on D5
 else
   PORTD &= ~bit (5); // turn off D5
 }  // end of myInterrupt

void setup ()
  { 
  attachInterrupt (0, myInterrupt, CHANGE);
  pinMode (2, INPUT_PULLUP);
  pinMode (5, OUTPUT);
  }  // end of setup

void loop ()
  {
  }

Ini membutuhkan 3,7 μs untuk mengubah pin tes, jauh lebih banyak daripada 1,6 μs di atas. Mengapa? Karena kode yang harus dikompilasi oleh kompiler untuk penangan interupsi "generik" harus menyimpan setiap register yang dapat dibayangkan (dorong mereka) saat masuk ke ISR, dan kemudian pulihkan (pop) sebelum kembali. Plus ada overhead panggilan fungsi lain.


Sekarang kita dapat mengatasinya dengan menghindari attachInterrupt () dan melakukannya sendiri:

ISR (INT0_vect)
 {
 if (PIND & bit (2))  // if it was high
   PORTD |= bit (5);  // turn on D5
 else
   PORTD &= ~bit (5); // turn off D5
 }  // end of INT0_vect

void setup ()
  { 
  // activate external interrupt 0

  EICRA &= ~(bit(ISC00) | bit (ISC01));  // clear existing flags
  EICRA |=  bit (ISC00);    // set wanted flags (any change interrupt)
  EIFR   =  bit (INTF0);    // clear flag for interrupt 0
  EIMSK |=  bit (INT0);     // enable it

  pinMode (2, INPUT_PULLUP);
  pinMode (5, OUTPUT);
  }  // end of setup

void loop ()
  {
  }

Itu adalah yang tercepat dari semuanya pada 1,52 μs - sepertinya satu siklus clock disimpan di suatu tempat.


Namun ada satu peringatan, untuk interupsi pin-change. Mereka batch, jadi jika Anda ingin memiliki interupsi pada banyak pin, Anda perlu menguji di dalam interupsi mana yang diubah. Anda bisa melakukannya dengan menyimpan status pin sebelumnya, dan membandingkannya dengan status pin baru. Ini belum tentu sangat lambat, tetapi semakin banyak pin yang perlu Anda periksa, semakin lambat itu.

Batch adalah:

  • A0 ke A5
  • D0 hingga D7
  • D8 ke D13

Jika Anda hanya ingin beberapa pin interupsi lagi, Anda dapat menghindari pengujian dengan hanya memilih untuk menggunakan pin dari batch yang berbeda (mis. D4 dan D8).


Lebih detail di http://www.gammon.com.au/interrupts

Nick Gammon
sumber
9

Ada dua jenis interupsi. Apa yang dikatakan Arduino Playground :

Prosesor di jantung setiap Arduino memiliki dua jenis interupsi yang berbeda: "eksternal", dan "perubahan pin". Hanya ada dua pin interupsi eksternal pada ATmega168 / 328 (yaitu, di Arduino Uno / Nano / Duemilanove), INT0 dan INT1, dan mereka dipetakan ke pin Arduino 2 dan 3. Interupsi ini dapat diatur untuk memicu pada RISING atau FALLING edge signal, atau pada level rendah. Pemicu ditafsirkan oleh perangkat keras, dan interupsi sangat cepat. Arduino Mega memiliki beberapa pin interupsi eksternal yang tersedia.

Di sisi lain interupsi penggantian pin dapat diaktifkan pada banyak pin lainnya. Untuk Arduino berbasis ATmega168 / 328, mereka dapat diaktifkan pada salah satu atau semua 20 pin sinyal Arduino; pada Arduinos berbasis ATmega mereka dapat diaktifkan pada 24 pin. Mereka dipicu secara sama pada tepi sinyal RISING atau FALLING, jadi terserah kode interupsi untuk mengatur pin yang tepat untuk menerima interupsi, untuk menentukan apa yang terjadi (pin mana? ... apakah sinyal naik, atau turun?), Dan untuk menanganinya dengan benar. Selain itu, interupsi penggantian pin dikelompokkan menjadi 3 “port” pada MCU, sehingga hanya ada 3 vektor interupsi (subrutin) untuk seluruh badan pin. Hal ini membuat pekerjaan menyelesaikan tindakan pada satu interupsi menjadi lebih rumit.

Pada dasarnya, gangguan eksternal sangat cepat karena semuanya berbasis perangkat keras. Namun, ada juga interupsi penggantian pin, tetapi yang tampaknya jauh lebih lambat karena mereka sebagian besar berbasis perangkat lunak.

tl; dr: 20 pin interupsi bersama jauh lebih lambat. 2 pin interupsi adalah yang tercepat dan paling efisien.


EDIT: Saya baru saja melihat datasheet dan mengatakan bahwa interupsi perubahan pin dipicu untuk salah satu pin yang dipilih tanpa ada indikasi pin mana yang telah berubah (walaupun dibagi menjadi tiga vektor interupsi).

  • Untuk interupsi eksternal, ini akan memberi tahu Anda pin 3 baru saja berubah
  • Untuk perubahan pin, ini akan memberi tahu Anda pin berubah yang sedang Anda pantau!

Seperti yang Anda lihat, interupsi penggantian pin menambahkan banyak overhead ke dalam ISR yang harus Anda tangani dengan menyimpan status sebelumnya dan melihat apakah pin yang Anda khawatirkan. Ini mungkin baik untuk keadaan tidur, tetapi lebih baik menggunakan interupsi eksternal.

Penguin Anonim
sumber