Bagaimana cara membuat interupsi timer dengan Arduino?

9

Saya mencoba membuat interupsi waktu tunda dengan Arduino. Saya ingin menggunakan fungsi interupsi (), karena ini adalah interupsi internal.

Contoh: Katakanlah, saya ingin membuat lampu berkedip dan mati, dengan hanya waktu interupsi.

Ada kode sampel, tetapi menggunakan interupsi eksternal (attachInterrupt ()). Saya ingin tetap menggunakan interupsi internal.

Tdk sengaja
sumber
2
Saya pikir poin yang juga ditunjukkan Kortuk adalah attachInterrupt adalah hal yang abstrak, Anda tidak memasang komponen eksternal :)
clabacchio
Artikel ini mungkin membantu Anda. engblaze.com/…
Seth Archer Brown

Jawaban:

10

Blog Noah Stahl memiliki contoh berkedip LED dengan Timer2 . Dengan itu dan lembar data, Anda harus dapat menyesuaikannya dengan interupsi mana pun yang ingin Anda gunakan - yaitu, interupsi yang fungsi normalnya paling Anda mampu untuk menyerah atau bersedia untuk memodifikasi. Timer2 biasanya digunakan untuk beberapa fungsi PWM.

Teladannya mengutip ATmega2560; Saya dapat mengonfirmasi bahwa ini bekerja dengan ATmega328p juga. Lihatlah sekeliling situsnya untuk contoh interupsi Arduino yang lebih berguna.

Edit:

Inilah sedikit kode saya yang diedit - kebanyakan dalam komentar - versi Nuh. Panggil Timer2init () dari fungsi pengaturan Arduino () setelah Anda menginisialisasi struktur data atau perangkat keras yang terkait, karena pengaturan waktu - dan interupsi - akan dimulai setelah Anda melakukannya.

F / ex, saya menggunakannya untuk multiplex tampilan 3-segmen 7-digit jadi saya sebelum menginisialisasi timer, saya menginisialisasi register display I / O dan mengapit data tampilan di tempat di mana ISR akan mencarinya.

Ada tabel di komentar dari beberapa data waktu yang berguna dari lembar-data dan perhitungan saya sendiri untuk referensi untuk mengatur skema waktu lain.

Makro ISR () mengatur pembuatan entri interupsi dan kode keluar untuk ISR alih-alih entri fungsi normal dan keluar, dan menghubungkannya dengan vektor interupsi yang tepat. Sisa dari fungsi itu adalah 1) kode yang akan dijalankan pada setiap interupsi, dan 2) kode kode untuk mengatur ulang timer untuk interupsi berikutnya.

Seperti yang tertulis, ini harus dimasukkan ke sketsa .pde atau .ino (atau file .cpp, jika Anda menggunakan eclipse, f / ex). Sketsa tersebut perlu #define LEDPIN, dan setup () perlu memanggil Timer2init (). Fungsi loop mungkin kosong atau tidak; LED harus mulai berkedip saat unduhan (yah, secara harfiah, setelah Timer2init () dipanggil).

/*
 * From sample interrupt code published by Noah Stahl on his blog, at:
 * http://arduinomega.blogspot.com/p/arduino-code.html
 * 
 */


/*** FUNC

Name:           Timer2init

Function:       Init timer 2 to interrupt periodically. Call this from 
                the Arduino setup() function.

Description:    The pre-scaler and the timer count divide the timer-counter
                clock frequency to give a timer overflow interrupt rate:

                Interrupt rate =  16MHz / (prescaler * (255 - TCNT2))

        TCCR2B[b2:0]   Prescaler    Freq [KHz], Period [usec] after prescale
          0x0            (TC stopped)     0         0
          0x1                1        16000.        0.0625
          0x2                8         2000.        0.500
          0x3               32          500.        2.000
          0x4               64          250.        4.000
          0x5              128          125.        8.000
          0x6              256           62.5      16.000
          0x7             1024           15.625    64.000


Parameters: void

Returns:    void

FUNC ***/

void Timer2init() {

    // Setup Timer2 overflow to fire every 8ms (125Hz)
    //   period [sec] = (1 / f_clock [sec]) * prescale * (255-count)
    //                  (1/16000000)  * 1024 * (255-130) = .008 sec


    TCCR2B = 0x00;        // Disable Timer2 while we set it up

    TCNT2  = 130;         // Reset Timer Count  (255-130) = execute ev 125-th T/C clock
    TIFR2  = 0x00;        // Timer2 INT Flag Reg: Clear Timer Overflow Flag
    TIMSK2 = 0x01;        // Timer2 INT Reg: Timer2 Overflow Interrupt Enable
    TCCR2A = 0x00;        // Timer2 Control Reg A: Wave Gen Mode normal
    TCCR2B = 0x07;        // Timer2 Control Reg B: Timer Prescaler set to 1024
}



/*** FUNC

Name:       Timer2 ISR

Function:   Handles the Timer2-overflow interrupt

Description:    Maintains the 7-segment display

Parameters: void

Returns:    void

FUNC ***/

ISR(TIMER2_OVF_vect) {
    static unsigned int led_state = 0; // LED state

    led_state = !led_state;         // toggles the LED state
    digitalWrite(TOGGLE_PIN, led_state);

    TCNT2 = 130;     // reset timer ct to 130 out of 255
    TIFR2 = 0x00;    // timer2 int flag reg: clear timer overflow flag
};
JRobert
sumber
(@Kortuk: Komentar yang Anda rujuk adalah pengamatan saya terhadap beberapa komentator di sini dan tidak ditujukan kepada Anda secara pribadi dan itu tidak perlu. Saya minta maaf dan saya telah menghapusnya.) Saya memperluas jawaban saya seperti yang Anda sarankan dan saya berharap itu sekarang tidak hanya demonstratif, tetapi juga instruktif. Ini termasuk komentar yang saya tulis ke dalam kode untuk saya gunakan sendiri (artinya: Jika saya bisa memahaminya 6 bulan dari sekarang, orang lain juga akan bisa), serta beberapa instruksi "bagaimana cara menggunakan" di menjawab. Terima kasih atas saran Anda.
JRobert
Perhatikan bahwa preskal 32 dan 128 tidak tersedia untuk timer0 dan timer1 (minimal dengan atmega328).
tuupola
Itu bagus untuk diketahui - terima kasih. Saya menggunakan ini untuk Timer2 (sejauh ini) dan itu pada dasarnya drop-in.
JRobert
5

Fungsi attachInterrupt () sebenarnya adalah melampirkan interupsi ke perubahan status eksternal pada pin, itu tidak memiliki opsi lain.

Pada halaman yang sama opsi mode terdaftar sebagai:

mode menentukan kapan interupsi harus dipicu. Empat batasan ditentukan sebagai nilai yang valid:

  • RENDAH untuk memicu interupsi setiap kali pin rendah,
  • Ganti untuk memicu interupsi setiap kali pin berubah nilainya
  • RISIKO untuk memicu ketika pin beralih dari rendah ke tinggi,
  • JATUH saat pin bergerak dari tinggi ke rendah.

Maaf menjadi pembawa berita buruk, itu adalah salah satu hal pertama yang saya cari.

Kortuk
sumber
Saya pikir maksudnya dia ingin menggunakan timer internal, daripada perangkat eksternal ... tapi saya tidak mengenal Arduino dengan baik, jadi saya tidak bisa mengatakan apakah itu mungkin
clabacchio
@clabacchio, saya mengatakan bahwa satu-satunya pilihan adalah menggunakan pemicu eksternal, tidak ada fungsi pengatur waktu internal.
Kortuk
Ah, bagus :) tapi setidaknya papan Arduino punya timer?
clabacchio
Ya, itulah cara mereka mencapai hal-hal seperti penundaan.
Kortuk
1
@ icarus74 ATMega328 benar-benar memiliki 3 timer (satu 16b dan dua 8b) tetapi semuanya digunakan oleh Arduino. Satu digunakan untuk fungsi seperti delay () dan millis () dan ketiganya digunakan untuk PWM (Anda dapat menemukan informasi lebih lanjut di fungsi 'init ()', file 'wiring.c' di Arduino IDE).
vasco
2

Ini artikel tentang PWM akan menghapus banyak keraguan Anda mengenai penggunaan Arduino timer. Ada dua timer 8-bit, dan satu timer 16-bit pada Arduino. Tidak ada API tingkat tinggi untuk mengaitkan fungsi ISR ​​langsung ke pengatur waktu, yang dikirimkan dengan Arduino SDK (yaitu sebagai pustaka standar), tetapi metode yang agak lebih rendah dalam pengaturan Special-Function-Register dan bit-arithmetic / operasi pada mereka. Namun ada perpustakaan kontribusi pengguna yang disebut Timer satu .

icarus74
sumber
Sebenarnya ada beberapa kombinasi timer yang berbeda tergantung pada Arduino mana yang sedang dirujuk. Jawabannya menyesatkan.
Sepertinya So
@ Dengan hormat. Jadi, ingin menguraikan? Jika Anda berbicara tentang perangkat keras Arduino, perhatikan bahwa jawabannya ada dalam konteks pertanyaan dan juga waktu ketika pertanyaan diajukan.
icarus74
Arduino Mega (berbasis ATmega1280) dirilis pada 26 Maret 2009, dan Mega 2560 (ATmega2560) dirilis pada 24 September 2010, jauh sebelum pertanyaan ini diajukan. Kedua mikrokontroler memiliki timer / counter 2x8 bit dan 1x16 bit lebih dari yang ditentukan dalam jawaban.
Sepertinya So
Sebagian besar interaksi yang saya lihat sejauh ini, memiliki referensi yang jelas untuk Arduino yang berarti seperti Duemilanove atau Uno yaitu papan berbasis seri 328. Papan lain selalu dikualifikasikan secara eksplisit oleh seri uP no. atau Mega, Nano, Mikro dll. Bagaimanapun, saya akan dengan rendah hati menerima koreksi. Dalam konteks ini, klarifikasi lebih baik.
icarus74
1

Arduino menggunakan ketiga timer di ATMega328. Timer1(16 bit) digunakan untuk fungsi seperti delay()dan millis()dan untuk output PWM pada pin 5 dan 6. Dua timer lainnya - Timer0dan Timer2digunakan untuk output PWM pada pin 3, 9, 10, 11.

Jadi, tidak ada fungsi Arduino untuk interupsi timer. Tapi ada cara. Anda dapat menggunakan kode ini untuk mengaktifkan penghentian waktu pada Timer2:

ISR(TIMER2_OVF_vect) {
  // Interrupt routine.
}

void setup() {
  // Enable Timer2 interrupt.
  TIMSK2 = (0<<OCIE2A) | (1<<TOIE2);
}

void loop() {
  // Your main loop.
}

Saya menulis kode ini tanpa pengujian, jadi mungkin saya membuat kesalahan. Dalam hal ini, periksa lembar data, hal.156 .

Jika Anda ingin mengubah frekuensi timer (prescaler), cukup ubah register TCCR2A. Untuk info lebih lanjut, lihat halaman lembar data 153. Tetapi jika Anda mengubah frekuensi pengatur waktu, Anda juga mengubah frekuensi sinyal PWM pada dua pin keluaran!

vasco
sumber
AFAIK pada ATmega328 Timer0dan Timer28 bit dan hanya Timer116 bit.
tuupola
Tidak, ini tidak benar. Ini adalah Timer0, bukan Timer1, yang digunakan untuk delay () dan millis () dan untuk output PWM pada pin 5 dan 6. Timer0 adalah timer 8-bit. Lihat misalnya Arduino Timers dan Interupsi .
Peter Mortensen