Arduino Timer Interrupts

Gagal pemasa membolehkan anda melakukan tugas pada selang waktu yang sangat teratur tanpa mengira apa lagi yang berlaku dalam kod anda. Di dalam pengajaran ini, saya akan menerangkan bagaimana untuk membuat persediaan dan melaksanakan interrupt dalam Pemasa Bersih pada Bandingkan Padanan atau Mod CTC. Lompat terus ke langkah 2 jika anda mencari kod sampel.

Biasanya apabila anda menulis lakaran Arduino Arduino melakukan semua arahan yang terkandung dalam fungsi gelung () {} dalam susunan yang ditulis, namun sukar untuk peristiwa masa dalam gelung (). Sesetengah arahan mengambil masa yang lebih lama daripada yang lain untuk dilaksanakan, ada yang bergantung kepada kenyataan bersyarat (jika, semasa ...) dan beberapa fungsi perpustakaan Arduino (seperti digitalWrite atau analogRead) terdiri daripada banyak arahan. Interruptor pemasa Arduino membolehkan anda untuk sementara menjeda urutan biasa peristiwa yang berlaku dalam fungsi gelung () pada jarak masa yang tepat, semasa anda menjalankan satu set perintah yang terpisah. Sebaik sahaja arahan ini dilakukan Arduino mengambil semula di mana ia berada dalam gelung ().

Interrupt berguna untuk:

Mengukur isyarat masuk pada selang jarak yang sama (frekuensi persampelan berterusan)

Mengira masa antara dua peristiwa

Menghantar isyarat frekuensi tertentu

Memeriksa secara berkala untuk data siri masuk

banyak lagi...

Terdapat beberapa cara untuk melakukan gangguan, untuk sekarang saya akan memberi tumpuan kepada jenis yang saya dapati yang paling berguna / fleksibel, dipanggil Clear Timer pada Match Match atau Mode CTC. Selain itu, dalam pengajaran ini saya akan menulis secara khusus mengenai pemasa untuk Arduino Uno (dan Arduino lain dengan ATMEL 328/168 ... Lilypad, Duemilanove, Diecimila, Nano ...). Idea utama yang dibentangkan di sini digunakan untuk papan Mega dan yang lebih tua juga, tetapi persediaannya sedikit berbeza dan jadual di bawah adalah khusus untuk ATMEL 328/168.

Langkah 1: Prescalers dan Bandingkan Match Match

The Uno mempunyai tiga timer yang dipanggil timer0, timer1, dan timer2. Setiap pemasa mempunyai kaunter yang bertambah pada setiap tanda jam pemasa. Interrupts pemasa CTC dicetuskan apabila kaunter mencapai nilai tertentu, disimpan dalam daftar perlawanan perbandingan. Sekali kaunter pemasa mencapai nilai ini, ia akan membersihkan (tetapkan semula kepada sifar) pada tanda semak jam pemasa seterusnya, maka ia akan terus mengira nilai pencocokan berbanding sekali lagi. Dengan memilih nilai padanan membandingkan dan menetapkan kelajuan di mana pemasa menaikkan kaunter, anda boleh mengawal kekerapan gangguan pemasa.

Parameter pertama yang saya bincangkan ialah kelajuan di mana pemasa menaikkan kaunter. Jam Arduino berjalan pada 16MHz, ini adalah kelajuan terpantas yang dapat meningkatkan bilangan pemain mereka. Pada 16MHz setiap tandakan daripada kaunter mewakili 1 / 16, 000, 000 dari kedua (~ 63ns), jadi kaunter akan mengambil 10/16, 000, 000 detik untuk mencapai nilai 9 (kaunter adalah 0 diindeks), dan 100/16, 000, 000 detik untuk mencapai nilai daripada 99.

Dalam banyak situasi, anda akan mendapati bahawa menetapkan kelajuan kaunter hingga 16MHz terlalu cepat. Timer0 dan timer2 adalah 8 bit timer, bermakna mereka boleh menyimpan nilai counter maksimum 255. Timer1 adalah pemasa 16 bit, bermakna ia boleh menyimpan nilai counter maksimum 65535. Setelah kaunter mencapai maksimum, ia akan menandakan kembali ke sifar (ini dipanggil limpahan). Ini bermakna pada 16MHz, walaupun jika kita menetapkan perbandingan perlawanan mendaftar ke nilai nilai max, gangguan akan berlaku setiap 256 / 16, 000, 000 detik (~ 16us) untuk 8 bit counter, dan setiap 65, 536 / 16, 000, 000 (~ 4 ms) saat untuk Kaunter 16 bit. Jelas sekali, ini tidak berguna jika anda hanya mahu mengganggu sekali sebulan.

Sebaliknya anda boleh mengawal kelajuan penambahan kaunter pemasa dengan menggunakan sesuatu yang dipanggil prescaler. Prescaler menetapkan kelajuan pemasa anda mengikut persamaan berikut:

(kelajuan pemasa (Hz)) = (Arduino clock speed (16MHz)) / prescaler

Jadi 1 prescaler akan menambah kaunter pada 16MHz, 8 prescaler akan menaikkannya pada 2MHz, 64 prescaler = 250kHz, dan sebagainya. Seperti yang ditunjukkan dalam jadual di atas, prescaler boleh sama dengan 1, 8, 64, 256, dan 1024. (Saya akan menerangkan maksud CS12, CS11, dan CS10 dalam langkah seterusnya.)

Sekarang anda boleh mengira kekerapan gangguan dengan persamaan berikut:

kekerapan gangguan (Hz) = (kelajuan jam Arduino 16, 000, 000Hz) / (prescaler * (bandingkan match register + 1))
+1 ada di sana kerana perbandingan sepadan bandingkan adalah sifar diindeks

menyusun semula persamaan di atas, anda boleh menyelesaikan untuk membandingkan nilai mendaftar perlawanan yang akan memberikan frekuensi gangguan yang anda inginkan:

bandingkan match register = [16, 000, 000Hz / (prescaler * frekuensi gangguan yang diingini)] - 1
ingat bahawa apabila anda menggunakan pemasa 0 dan 2, nombor ini mestilah kurang dari 256, dan kurang daripada 65536 untuk pemasa1

jadi jika anda mahu mengganggu setiap detik (kekerapan 1Hz):
bandingkan match register = [16, 000, 000 / (prescaler * 1)] -1
dengan prescaler sebanyak 1024 anda dapat:
bandingkan match register = [16, 000, 000 / (1024 * 1)] -1
= 15, 624
sejak 256 <15624 <65.536, anda mesti menggunakan timer1 untuk gangguan ini.

Langkah 2: Penyusunan Penstrukturan Pemasa


Kod persediaan pemasa dilakukan di dalam fungsi persediaan () {} dalam lakaran Arduino.

Kod yang terlibat untuk menubuhkan penggantungan pemasa adalah sedikit menakutkan untuk melihat, tetapi sebenarnya tidak begitu sukar. Saya cukup banyak menyalin bahagian utama kod yang sama dan menukar prescaler dan bandingkan senarai padanan untuk menetapkan kekerapan gangguan yang betul.

Struktur utama persediaan gangguan kelihatan seperti ini:
 ////www.instructables.com/id/Arduino-Timer-Interrupts/setup void setup () cli (); // stop interrupts // set timer0 interrupt at 2kHz TCCR0A = 0; // set whole TCCR0A register to 0 TCCR0B = 0; // sama dengan TCCR0B TCNT0 = 0; // menginisialisasi nilai penolakan kepada 0 / / set bandingkan perbandingan padanan untuk kenaikan 2khz OCR0A = 124; // = (16 * 10 ^ 6) / (2000 * 64) - 1 (mestilah <256) // hidupkan mod CTC TCCR0A // persediaan akhir 
Perhatikan bagaimana nilai OCR # A (nilai padanan bandingkan) untuk setiap seting pemasa ini. Seperti yang dijelaskan dalam langkah terakhir, ini dikira mengikut persamaan berikut:

bandingkan match register = [16, 000, 000Hz / (prescaler * frekuensi gangguan yang diingini)] - 1
ingat bahawa apabila anda menggunakan pemasa 0 dan 2, nombor ini mestilah kurang dari 256, dan kurang daripada 65536 untuk pemasa1

Juga perhatikan bagaimana persediaan antara tiga pemasa berbeza sedikit dalam garisan yang menghidupkan mod CTC:
TCCR0A | = (1 << WGM01); // untuk pemasa0
TCCR1B | = (1 << WGM12); // untuk pemasa1
TCCR2A | = (1 << WGM21); // untuk pemasa2
Ini secara langsung mengikuti lembaran data ATMEL 328/168.

Akhir sekali, perhatikan bagaimana persediaan untuk preskaler mengikuti jadual dalam langkah terakhir (jadual untuk pemasa 0 diulang di atas),
TCCR2B | = (1 << CS22); // Set CS # 2 bit untuk 64 prescaler untuk pemasa 2
TCCR1B | = (1 << CS11); // Tetapkan CS # 1 bit untuk 8 prescaler untuk pemasa 1
TCCR0B | = (1 << CS02) | (1 << CS00); / / Set CS # 2 dan CS # 0 bit untuk 1024 prescaler untuk pemasa 0

Perhatikan dalam langkah terakhir bahawa terdapat pilihan yang berbeza bagi pemasa yang berbeza. Contohnya, timer2 tidak mempunyai pilihan 1024 prescaler.

Perintah yang ingin anda laksanakan semasa gangguan pemasa ini terletak dalam lakaran Arduino yang terkandung dalam perkara berikut:
ISR (TIMER0_COMPA_vect) {// tukar 0 hingga 1 untuk pemasa1 dan 2 untuk pemasa2
/ / // arahan mengganggu di sini
}
Bit kod ini harus terletak di luar fungsi persediaan () dan gelung (). Juga, cuba simpan rutin mengganggu sesedikit mungkin, terutamanya jika anda mengganggu pada frekuensi tinggi. Ia mungkin bernilai menangani port / pin cip ATMEL secara langsung dan bukan menggunakan fungsi digitalWrite () dan digitalRead (). Anda boleh mendapatkan maklumat lanjut mengenai perkara itu di sini.

Contohnya - lakaran berikut menetapkan dan melaksanakan 3 senggang pemasa:

 / // pemasa mengganggu // oleh Amanda Ghassaei // Jun 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Program ini adalah perisian percuma; anda boleh mengagihkan semula dan / atau mengubah suai * ia di bawah terma GNU General Public License seperti yang diterbitkan oleh * Yayasan Perisian Bebas; sama ada versi 3 Lesen, atau * (pada pilihan anda) mana-mana versi yang lebih baru. * * / // persediaan pemasa untuk timer0, timer1, dan timer2. // Untuk arduino uno atau mana-mana papan dengan ATMEL 328/168 .. diecimila, duemilanove, lilypad, nano, mini ... // kod ini akan membolehkan semua tiga pemasa arduino mengganggu. // timer0 akan mengganggu pada 2kHz // pemasa1 akan mengganggu pada 1Hz // timer2 akan mengganggu pada 8kHz // pembolehubah penyimpanan boolean toggle0 = 0; boolean toggle1 = 0; boolean toggle2 = 0; void setup () // set pins sebagai output pinMode (8, OUTPUT); pinMode (9, OUTPUT); pinMode (13, OUTPUT); cli (); // stop interrupts // set timer0 interrupt at 2kHz TCCR0A = 0; // set all TCCR2A register to 0 TCCR0B = 0; // same for TCCR2B TCNT0 = 0; // initialize counter counter to 0 // set bandingkan perbandingan padanan untuk kenaikan 2khz OCR0A = 124; // = (16 * 10 ^ 6) / (2000 * 64) - 1 (mesti <256) // menghidupkan mod CTC TCCR0A // end setup ISR (TIMER0_COMPA_vect) { / // timer0 mengganggu 2kHz toggles pin 8 // menghasilkan gelombang denyut frekuensi 2kHz / 2 = 1kHz (mengambil dua kitaran untuk gelombang penuh - togol tinggi kemudian togol rendah) jika (toggle0) {digitalWrite (8, TINGGI); toggle0 = 0; } else {digitalWrite (8, LOW); toggle0 = 1; }} ISR (TIMER1_COMPA_vect) {// timer1 interrupt 1Hz toggles pin 13 (LED) // menghasilkan gelombang denyut frekuensi 1Hz / 2 = 0.5kHz (mengambil dua siklus untuk gelombang penuh beralih tinggi kemudian togol rendah) jika (toggle1) digitalWrite (13, TINGGI); toggle1 = 0; } else {digitalWrite (13, LOW); toggle1 = 1; }} ISR (TIMER2_COMPA_vect) {// timer1 mengganggu 8kHz toggles pin 9 // menghasilkan gelombang denyut frekuensi 8kHz / 2 = 4kHz (mengambil dua kitaran untuk gelombang penuh - togol tinggi kemudian togol rendah) jika (toggle2) {digitalWrite (9, TINGGI); toggle2 = 0; } else {digitalWrite (9, LOW); toggle2 = 1; }} void loop () {// do things here here} 

Imej-imej di atas menunjukkan output dari gangguan pemasa ini. Rajah 1 menunjukkan gelombang persegi berayun antara 0 dan 5V pada 1kHz (pemasa timer0), rajah 2 menunjukkan LED dipasang pada pin 13 menyalakan untuk satu saat kemudian mematikan untuk satu saat (interrupt timer1), rajah 3 menunjukkan gelombang denyutik berayun antara 0 dan 5V pada frekuensi 4khz (timer2 mengganggu).

Langkah 3: Contoh 1: Speedometer Basikal

Dalam contoh ini, saya membuat speedometer basikal berkuasa arduino. Ia berfungsi dengan melampirkan magnet ke roda dan mengukur jumlah masa yang diperlukan untuk lulus dengan suis magnet dipasang pada bingkai-masa untuk satu putaran lengkap roda.

Saya menetapkan pemasa 1 untuk mengganggu setiap ms (kekerapan 1kHz) untuk mengukur suis magnet. Sekiranya magnet sedang lulus dengan suis, isyarat dari suis adalah tinggi dan "masa" berubah menjadi sifar. Sekiranya magnet tidak berada berhampiran dengan "masa" suis, kenaikan dengan 1. Dengan cara ini "masa" sebenarnya hanya pengukuran jumlah masa dalam milisaat yang telah berlalu sejak magnet terakhir diluluskan oleh suis magnet. Maklumat ini digunakan kemudian dalam kod untuk mengira rpm dan mph basikal.

Berikut adalah sedikit kod yang menetapkan pemasa1 untuk 1kHz mengganggu

cli (); // stop interrupts
// set timer1 mengganggu pada 1kHz
TCCR1A = 0; // set keseluruhan TCCR1A mendaftar kepada 0
TCCR1B = 0; // sama untuk TCCR1B
TCNT1 = 0; // memulakan nilai counter kepada 0
/ // menetapkan jumlah pemasa untuk kenaikan 1khz
OCR1A = 1999; // = (16 * 10 ^ 6) / (1000 * 8) - 1
// terpaksa menggunakan pemasa 16 bit1 untuk ini bc 1999> 255, tetapi boleh beralih ke pemasa 0 atau 2 dengan prescaler yang lebih besar
// hidupkan mod CTC
TCCR1B | = (1 << WGM12);
// Tetapkan CS11 bit untuk 8 prescaler
TCCR1B | = (1 << CS11);
// membolehkan pemasa membandingkan gangguan
TIMSK1 | = (1 << OCIE1A);
sei (); / / membenarkan interupsi

Inilah kod lengkap jika anda ingin melihat:
 // speedometer basikal // oleh Amanda Ghassaei 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * This program adalah perisian percuma; anda boleh mengagihkan semula dan / atau mengubah suai * ia di bawah terma GNU General Public License seperti yang diterbitkan oleh * Yayasan Perisian Bebas; sama ada versi 3 Lesen, atau * (pada pilihan anda) mana-mana versi yang lebih baru. * * / // pengiraan sampel // jejari tayar ~ 13.5 inci // lingkaran = pi * 2 * r = ~ 85 inci // max speed 35mph = ~ 616inches / second // max rps = ~ 7.25 #define reed A0 / / pin disambungkan ke suis baca // pembolehubah penyimpanan jejari terapung = 13.5; // jejari tayar (dalam inci) - GANTI INI UNTUK BANDUNG SENDIRI SENDIRI; masa yang panjang = 0; // masa antara satu putaran penuh (dalam ms) float mph = 0.00; lilungan terapung; lampu belakang boolean; int maxReedCounter = 100; // masa min (dalam ms) satu putaran (untuk debouncing) int reCounter; void setup () {reedCounter = maxReedCounter; lingkaran = 2 * 3.14 * radius; pinMode (1, OUTPUT); // tx pinMode (2, OUTPUT); // suis lampu belakang pinMode (reed, INPUT); // redd switch checkBacklight (); Serial.write (12); // clear // TIMER SETUP - interrupt timer membolehkan preceise ukuran masa swap reed // untuk maklumat mor mengenai konfigurasi arduino timers lihat //arduino.cc/playground/Code/Timer1 cli ( // stop interrupts // set timer1 interrupt pada 1kHz TCCR1A = 0; // set keseluruhan TCCR1A mendaftar ke 0 TCCR1B = 0; // sama untuk TCCR1B TCNT1 = 0; // memulakan nilai counter kepada 0; / // menetapkan bilangan pemasa untuk kenaikan 1khz OCR1A = 1999; // = (16 * 10 ^ 6) / (1000 * 8) - 1 / / // mengaktifkan mod CTC TCCR1B | = (1 << WGM12); // Set CS11 bit untuk 8 prescaler TCCR1B | = (1 << CS11); / / membolehkan pemasa membandingkan interrupt TIMSK1 | = (1 <0) {// jangan biarkan reedCounter pergi reedCounter negatif - = 1; // penundaan reedCounter}}} else {// if switch reed open if (reedCounter> 0 ) {// jangan biarkan reedCounter pergi reedCounter negatif - = 1; // decrement reedCounter}} if (time> 2000) {mph = 0; // jika tiada pulsa baru dari tukar ganti tayar tetap, tetapkan mph ke 0} else {time + = 1; // timer pemula}} void displayMPH () {Serial.write (12); // clear Serial.write ("Speed ​​="); Serial.write (13); // memulakan baris baru Serial.print (mph); Serial.write ("MPH"); //Serial.write("0.00 MPH "); } void loop () {// print mph once displayMPH (); kelewatan (1000); checkBacklight (); } 

Langkah 4: Contoh 2: Komunikasi Serial

Projek ini ialah pad butang backlit 4x4. Projek ini menghubungkan ke komputer saya melalui usb, ia menghantar maklumat mengenai butang ke komputer dan menerima maklumat tentang cara menyalakan LED. Berikut ialah video:



Untuk projek ini, saya menggunakan pemasaan timer2 untuk memeriksa secara berkala jika ada data siri masuk, membacanya, dan simpannya dalam matrik "ledData []". Sekiranya anda memerhatikan kod tersebut, anda akan melihat bahawa gelung utama lakaran adalah apa yang sebenarnya bertanggungjawab untuk menggunakan maklumat dalam ledData untuk menyalakan LED yang betul dan menyemak status butang (fungsi yang dipanggil "shift ( ) "). Rutin mengganggu adalah sesingkat mungkin - hanya semak bait masuk dan menyimpannya dengan sewajarnya.

Berikut ialah persediaan untuk pemasa2:

cli (); // stop interrupts
// set timer2 mengganggu setiap 128us
TCCR2A = 0; / set keseluruhan TCCR2A mendaftar kepada 0
TCCR2B = 0; // sama untuk TCCR2B
TCNT2 = 0; // memulakan nilai counter kepada 0
/ / set bandingkan senarai padanan untuk kenaikan 7.8khz
OCR2A = 255; // = (16 * 10 ^ 6) / (7812.5 * 8) - 1 (mesti <256)
// hidupkan mod CTC
TCCR2A | = (1 << WGM21);
// Set CS21 bit untuk 8 prescaler
TCCR2B | = (1 << CS21);
// membolehkan pemasa membandingkan gangguan
TIMSK2 | = (1 << OCIE2A);
sei (); / / membenarkan interupsi

Berikut adalah lakaran Arduino yang lengkap:
 / // BUTTON TEST w / 74HC595 dan 74HC165 dan komunikasi siri // oleh Amanda Ghassaei // Jun 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Program ini adalah perisian percuma; anda boleh mengagihkan semula dan / atau mengubah suai * ia di bawah terma GNU General Public License seperti yang diterbitkan oleh * Yayasan Perisian Bebas; sama ada versi 2 Lesen, atau * (pada pilihan anda) mana-mana versi yang lebih baru. * * / // firmware ini akan menghantar data bolak-balik dengan patch maxmsp "beat slicer" // pin sambungan #define ledLatchPin A1 #define ledClockPin A0 #define ledDataPin A2 #define buttonLatchPin 9 #define buttonClockPin 10 #define buttonDataPin A3 / / perulangan pembolehubah byte i; bait j; byte k; byte ledByte; // storan untuk negeri yang dipimpin, 4 bait byte ledData [] = {0, 0, 0, 0}; // penyimpanan untuk butang, 4 byte byte buttonCurrent [] = {0, 0, 0, 0}; butang byteLast [] = {0, 0, 0, 0}; button byte [] = {0, 0, 0, 0}; byte buttonState [] = {0, 0, 0, 0}; / butang butang debounce counter- 16 bytes buttonDebounceCounter [4] [4]; void setup () = (1 << WGM21); // Set CS21 bit untuk 8 prescaler TCCR2B // buttonCheck - periksa keadaan butang yang diberikan. // fungsi penekanan butang ini sebahagian besarnya disalin daripada firmware monok 40h oleh crabtree brian dan kekunci joe lake voidcheck (baris byte, byte index) {jika (((butang [Baris semasa [row] ^ buttonLast [baris]) & (1 << indeks) ) && // jika keadaan butang fizikal semasa adalah berbeza daripada butang ((butang [Baris semasa] butang butang [Baris] [&] (1 << indeks))) {// butang butang fizikal lepas DAN keadaan debar semasa jika (butang semasa [baris] & (1 << indeks)) // jika butang butang fizikal semasa menekan butangEvent [baris] = 1 << indeks; // antrean acara butang baru segera butangState [baris] lain {buttonDebounceCounter [row] [index] = 12; } // jika tidak, butang sebelum ini tertekan dan kini // telah dikeluarkan supaya kami menetapkan kaunter debounce kami. } jika jika (((butang [Baris] ^ butangLast [baris] sekarang & (1 << indeks)) == 0 && // jika butang butang fizikal semasa adalah sama dengan (butang [ ) & (1 <0 && --buttonDebounceCounter [row] [index] == 0) {// jika kaunter debounce telah / telah diturunkan kepada 0 (bermaksud // butang telah terpasang untuk // kButtonUpDefaultDebounceCount / / lajur /// butangEvent [baris] = 1 << indeks; // barisan sehingga acara perubahan keadaan butang jika (butang [Baris semasa] & (1 << indeks)) = (1 << index); else {buttonState [ (1 <indeks);}}}} void shift () {untuk (i = 0; i <4; i ++) {buttonLast [i] = buttonSurrent [i]; byte dataToSend = > 3; // latchpin low digitalWrite (buttonLatchPin, LOW); untuk (k = 0; k <4; k ++) {buttonCheck (i, k); if (buttonEvent [i]  1) & 3; byte ledx = (ledByte >> 3) & 3; jika (ledstate) = 8 >> ledx; lain {ledData [ledy] & = ~ (8 >> ledx); }} // akhir sekiranya tersedia siri} / // akhir lakukan semasa (Serial.available ()> 8); } void loop () {shift (); // updates leds and receive data from buttons} 

muat turun patch MaxMSP di bawah (ia akan berjalan di Max Runtime juga).

Lampiran

  • mengalahkan slicer.zip Muat turun

Langkah 5: Contoh 3: DAC

Dalam projek ini saya menggunakan gangguan pemasa untuk menghasilkan gelombang sinus frekuensi khusus dari Arduino. Saya menyalurkan DAC R2R 8 bit sederhana ke pin digital 0-7. DAC ini dibina dari 10k dan 20k resistor yang disusun dalam pembahagi voltan pelbagai peringkat. Saya akan memaparkan lebih banyak mengenai pembinaan DAC dalam satu lagi pengajaran, kerana sekarang saya telah memasukkan foto di atas.
Saya menyambung output dari DAC sehingga osiloskop. Sekiranya anda memerlukan bantuan memahami cara menggunakan / baca oscilloscope periksa tutorial ini. Saya memuatkan kod berikut ke Arduino:
 // 63Hz gelombang sinus // oleh Amanda Ghassaei 2012 ////www.instructables.com/id/Arduino-Timer-Interrupts/ / * * Program ini adalah perisian percuma; anda boleh mengagihkan semula dan / atau mengubah suai * ia di bawah terma GNU General Public License seperti yang diterbitkan oleh * Yayasan Perisian Bebas; sama ada versi 3 Lesen, atau * (pada pilihan anda) mana-mana versi yang lebih baru. * * // // menghantar gelombang sinus 63Hz ke arduino PORTD DAC float t = 0; void setup () = (1 << CS21); / // membolehkan pemasa membandingkan interrupt TIMSK2 ISR (TIMER2_COMPA_vect) {// increment t t + = 1; jika (t == 628) {// 40kHz / 628 = ~ 63Hz t = 0; }} void loop () {// gelombang sinus frekuensi ~ 63Hz // hantar nilai sinus ke PORTD antara 0 dan 255 PORTD = byte (127 + 127 * sin (t / 100)); } 
Saya menubuhkan satu pemasa yang mengganggu yang menaikkan t variable pada kekerapan 40kHz. Sebaik sahaja t mencapai 627 ia semula semula ke sifar (ini berlaku dengan kekerapan 40, 000 / 628 = 63Hz). Sementara itu, dalam gelung utama Arduino menghantar nilai antara 0 (00000000 dalam binari) dan 255 (11111111 dalam binari) kepada pin digital 0 hingga 7 (PORTD). Ia mengira nilai ini dengan persamaan berikut:

PORTD = byte (127 + 127 * sin (t / 100));

Jadi, sebagai kenaikan t dari 0 hingga 627 fungsi sinus bergerak melalui satu kitaran lengkap. Nilai yang dihantar ke PORTD adalah gelombang sinus dengan kekerapan 63Hz dan amplitud 127, berayun sekitar 127. Apabila ini dihantar melalui tangga 8 resistor DAC ia menghasilkan isyarat berayun sekitar 2.5V dengan amplitud 2.5V dan kekerapan 63Hz.

Kekerapan gelombang sinus boleh dua kali ganda dengan mendarabkan tempoh (t / 100) dengan 2, empat kali ganda dengan mendarabkan sebanyak 4, dan sebagainya ...
Juga perhatikan bahawa jika anda meningkatkan kekerapan gangguan pemasa terlalu banyak dengan mengurangkan prescaler atau OCR2A gelombang sinus tidak akan dikeluarkan dengan betul. Ini adalah kerana fungsi sin () adalah sangat mahal, dan pada frekuensi gangguan yang tinggi ia tidak mempunyai masa yang cukup untuk dilaksanakan. Jika anda menggunakan gangguan kekerapan yang tinggi, bukannya melakukan perhitungan semasa rutin mengganggu, memandangkan menyimpan nilai-nilai dalam array dan hanya memanggil nilai-nilai ini menggunakan beberapa jenis indeks. Anda boleh mencari contohnya dalam generator gelombang arduino saya - dengan menyimpan 20, 000 nilai dosa dalam array, saya dapat mengeluarkan gelombang sinus dengan frekuensi persampelan 100kHz.

Langkah 6: Fungsi Pemasa dan Arduino

Satu perkara yang perlu diperhatikan- setup timer tertentu sebenarnya akan mematikan beberapa fungsi perpustakaan Arduino. Timer0 digunakan oleh fungsi millis () dan kelewatan (), jika anda secara manual menetapkan timer0, fungsi-fungsi ini tidak akan berfungsi dengan betul.
Selain itu, ketiga-tiga pemasa menanggung jawatan analogWrite (). Secara automatik menetapkan pemasa akan menghentikan analogWrite () daripada berfungsi.

Jika terdapat beberapa bahagian kod anda yang anda tidak mahu terganggu, dengan mempertimbangkan menggunakan cli () dan sei () untuk melumpuhkan secara global dan membolehkan gangguan.

Anda boleh membaca lebih lanjut mengenai ini di laman web Arduino.

Artikel Berkaitan