Mengganggu menggunakan pemasa dalaman Arduino. Gangguan dan multitasking dalam Arduino. Apa yang boleh dilakukan oleh pemasa?

Mari belajar cara bekerja dengan gangguan pemasa. Mari kita tulis program mudah dengan proses selari.

Dalam program sebenar, banyak tindakan mesti dilakukan serentak. Dalam pendahuluan saya memberi contoh. Biar saya senaraikan tindakan yang dia lakukan:

Operasi

Masa kitaran
Menyoal siasat 3 butang, memproses isyarat daripadanya untuk menghapuskan lantunan 2 ms
Menjana semula data daripada penunjuk LED tujuh segmen 2 ms
Menjana isyarat kawalan untuk 2 penderia suhu DS18B20 dan membaca data daripadanya. Penderia mempunyai antara muka bersiri 1 wayar. 100 µs untuk setiap bit,
1 saat jumlah kitaran bacaan
Membaca nilai analog arus dan voltan pada elemen Peltier, voltan bekalan 100 µs
Penapisan digital nilai arus dan voltan analog 10 ms
Pengiraan kuasa pada elemen Peltier 10 ms
PID (proportional integral differential) pengawal penstabilan arus dan voltan 100 µs
Pengatur kuasa 10 ms
Pengawal suhu 1 saat
Fungsi keselamatan, pemantauan integriti data 1 saat
Pengurusan, logik am operasi sistem 10 ms

Semua operasi ini dilakukan secara kitaran, setiap satu dengan tempoh kitaran yang berbeza. Tiada seorang pun daripada mereka boleh digantung. Sebarang perubahan, walaupun jangka pendek, dalam masa tempoh operasi akan membawa kepada masalah: ralat pengukuran yang ketara, operasi penstabil yang tidak betul, penunjuk berkelip, tindak balas yang tidak stabil pada tekanan butang, dsb.

Dalam program pengawal peti sejuk, terdapat beberapa proses selari yang melakukan semua tindakan ini, setiap satu dalam kitaran dengan masa tempohnya sendiri. Proses selari ialah proses yang tindakannya dilakukan secara serentak.

Dalam pelajaran sebelumnya kami mencipta kelas untuk objek butang. Kami mengatakan bahawa ini adalah kelas untuk memproses isyarat dalam proses selari. Bahawa untuk operasi normalnya adalah perlu untuk memanggil fungsi pemprosesan isyarat (kaedah) dalam kitaran dengan tempoh tetap (kami memilih masa 2 ms). Dan kemudian, di mana-mana sahaja dalam program, tanda tersedia yang menunjukkan keadaan semasa butang atau isyarat.

Dalam satu gelung kami meletakkan kod untuk memproses keadaan butang dan mengawal LED. Dan pada penghujung gelung kami menetapkan kelewatan fungsi kelewatan(2). Tetapi, masa yang diperlukan untuk melaksanakan program dalam gelung mengubah jumlah masa gelung. Dan tempoh kitaran jelas tidak sama dengan 2 ms. Di samping itu, semasa pelaksanaan fungsi delay(), program akan membeku dan tidak boleh melakukan tindakan lain. Program yang kompleks akan mengakibatkan huru-hara sepenuhnya.

Keluar - panggil fungsi untuk memproses keadaan butang apabila gangguan daripada pemasa perkakasan. Setiap 2 ms gelung program utama mesti terganggu, isyarat butang diproses dan kawalan kembali ke gelung utama kepada kod di mana ia terganggu. Masa yang singkat untuk memproses isyarat butang tidak akan menjejaskan pelaksanaan gelung utama dengan ketara. Itu. Pemprosesan butang akan berlaku secara selari, tanpa disedari oleh program utama.

Gangguan pemasa perkakasan.

Gangguan perkakasan ialah isyarat yang melaporkan beberapa peristiwa. Apabila tiba, pelaksanaan program digantung dan kawalan diserahkan kepada pengendali gangguan. Selepas pemprosesan, kawalan kembali kepada kod program yang terganggu.

Dari sudut pandangan program, gangguan ialah panggilan fungsi disebabkan oleh peristiwa luaran yang tidak berkaitan secara langsung dengan kod program.

Isyarat gangguan pemasa dijana secara kitaran, dengan tempoh masa yang ditentukan. Ia dijana oleh pemasa perkakasan - pembilang dengan logik yang menetapkan semula kodnya apabila nilai tertentu dicapai. Dengan menetapkan kod secara pemrograman untuk logik tetapan semula, kita boleh menetapkan masa tempoh gangguan pemasa.

Menetapkan mod dan masa tempoh pemasa Arduino dilakukan melalui daftar perkakasan mikropengawal. Jika anda mahu, anda boleh memikirkan bagaimana ini dilakukan. Tetapi saya mencadangkan pilihan yang lebih mudah - menggunakan perpustakaan MsTimer2. Selain itu, menetapkan mod pemasa jarang berlaku, yang bermaksud bahawa menggunakan fungsi perpustakaan tidak akan melambatkan program.

Perpustakaan MSTimer2.

Perpustakaan ini bertujuan untuk mengkonfigurasi gangguan perkakasan daripada Pemasa 2 mikropengawal. Ia hanya mempunyai tiga fungsi:

  • MsTimer2::set(ms panjang tidak ditandatangani, batal (*f)())

Fungsi ini menetapkan masa tempoh gangguan dalam ms. Pengendali gangguan f akan dipanggil dengan tempoh ini. Ia mesti diisytiharkan batal (tidak mengembalikan apa-apa) dan tidak mempunyai hujah. * f ialah penunjuk fungsi. Sebaliknya, anda perlu menulis nama fungsi tersebut.

  • MsTimer2::start()

Fungsi ini membolehkan gangguan pemasa.

  • MsTimer2::stop()

Fungsi ini melumpuhkan gangguan pemasa.

Sebelum nama fungsi anda perlu menulis MsTimer2::, kerana Perpustakaan ditulis menggunakan arahan ruang nama.

Untuk memasang perpustakaan, salin direktori MsTimer2 ke folder perpustakaan dalam folder kerja Arduino IDE. Kemudian lancarkan program IDE Arduino, buka Lakaran -> Sambungkan perpustakaan dan lihat bahawa perpustakaan MsTimer2 hadir dalam senarai perpustakaan.

Anda boleh memuat turun perpustakaan MsTimer2 dalam arkib zip. Untuk memasangnya, anda perlu membongkarnya.

Program mudah dengan pemprosesan selari isyarat butang.

Sekarang mari kita tulis program mudah dengan satu butang dan LED dari pelajaran 6. Satu butang disambungkan ke papan Arduino mengikut rajah:

Ia kelihatan seperti ini:

Untuk setiap butang ditekan, LED pada papan Arduino menukar keadaannya. Perpustakaan MsTimer2 dan Button perlu dipasang:

MsTimer2

Dan bayar. Hanya 25 gosok. sebulan untuk akses kepada semua sumber tapak!

// lakaran_10_1 pelajaran 10
// Menekan butang mengubah keadaan LED

#termasuk
#termasuk

#define LED_1_PIN 13 //
#define BUTTON_1_PIN 12 // butang disambungkan ke pin 12

Butang butang1(BUTTON_1_PIN, 15); // penciptaan objek - butang

persediaan batal() (

MsTimer2::set(2, timerInterrupt); // tetapkan tempoh gangguan pemasa kepada 2 ms
MsTimer2::start(); //
}

gelung kosong() (

// Kawalan LED
jika (button1.flagClick == benar) (
// butang telah diklik



}
}

// pengendali gangguan
pemasa batalInterrupt() (
butang1.scanState(); // memanggil kaedah untuk menunggu keadaan stabil untuk butang
}

Dalam fungsi setup(), kami menetapkan masa kitaran gangguan pemasa kepada 2 ms dan nyatakan nama pemasa pengendali gangguanInterrupt . Butang fungsi pemprosesan isyarat butang1.scanState() dipanggil dalam pengendali gangguan pemasa setiap 2 ms.

Oleh itu, kami memproses keadaan butang dalam proses selari. Dan dalam gelung utama program kami menyemak tanda klik butang dan menukar keadaan LED.

Kelayakan yang tidak menentu.

Mari kita ubah suai gelung gelung() dalam atur cara sebelumnya.

gelung kosong() (

manakala(benar) (
jika (button1.flagClick == benar) putus;
}

// butang telah diklik
butang1.flagClick= palsu; // set semula tanda
digitalWrite(LED_1_PIN, ! digitalRead(LED_1_PIN)); // Penyongsangan LED
}

Secara logiknya tiada apa yang berubah.

  • Dalam versi pertama, program ini melalui gelung hingga akhir dan menganalisis bendera button1.flagClick di dalamnya.
  • Dalam pilihan kedua, program menganalisis bendera button1.flagClick dalam gelung sementara yang tidak berkesudahan. Apabila bendera menjadi aktif, ia keluar dari gelung sementara melalui putus dan menyongsangkan keadaan LED.

Satu-satunya perbezaan adalah dalam kitaran mana program berjalan dalam gelung atau sementara.

Tetapi jika kami menjalankan versi terkini program, kami akan melihat bahawa LED tidak bertindak balas kepada penekanan butang. Mari keluarkan kelas dan mudahkan atur cara.

#termasuk
#define LED_1_PIN 13 // LED disambungkan ke pin 13
int count=0;

persediaan batal() (
pinMode(LED_1_PIN, OUTPUT); // tentukan pin LED sebagai output
MsTimer2::set(500, timerInterrupt); // tetapkan tempoh gangguan pemasa kepada 500 ms
MsTimer2::start(); // dayakan gangguan pemasa
}

gelung kosong() (

manakala (benar) (
jika (kira!= 0) pecah;
}

kiraan= 0;
digitalWrite(LED_1_PIN, ! digitalRead(LED_1_PIN)); // Penyongsangan keadaan LED
}

// pengendali gangguan
pemasa batalInterrupt() (
kira++;
}

Dalam program ini, pembilang kiraan dinaikkan sebanyak 1 dalam pengendali gangguan setiap 500 ms. Dalam gelung sementara ia dianalisis, dengan rehat kita keluar dari gelung dan terbalikkan keadaan LED. Anda tidak dapat membayangkan program yang lebih mudah, tetapi ia tidak berfungsi sama ada.

Hakikatnya ialah pengkompil bahasa C++ mengoptimumkan program mengikut kecerdasannya. Kadang-kadang ini tidak berfungsi dengan baik. Pengkompil melihat bahawa tiada operasi dilakukan pada pembolehubah kiraan dalam gelung while. Oleh itu, beliau percaya bahawa cukup untuk menyemak keadaan kiraan sekali sahaja. Mengapa menyemak dalam gelung sesuatu yang tidak boleh berubah. Pengkompil membetulkan kod, mengoptimumkannya untuk masa pelaksanaan. Ringkasnya, ia mengalih keluar kod semakan pembolehubah dari gelung. Pengkompil tidak dapat memahami bahawa pembolehubah kiraan mengubah keadaannya dalam pengendali gangguan. Akibatnya, kita terperangkap dalam gelung while.

Dalam versi program yang melaksanakan gelung sehingga akhir, pengkompil menganggap bahawa semua pembolehubah boleh berubah dan meninggalkan kod semakan. Jika anda memasukkan panggilan ke mana-mana fungsi sistem ke dalam gelung while, pengkompil juga akan memutuskan bahawa pembolehubah boleh berubah.

Jika, sebagai contoh, anda menambah panggilan pada fungsi delay() pada gelung while, program akan berfungsi.

manakala (benar) (
jika (kira != 0) pecah;
kelewatan(1);
}

Gaya yang baik adalah untuk membangunkan program di mana gelung dilaksanakan hingga akhir dan program tidak membeku di mana-mana sahaja. Pelajaran seterusnya akan mengandungi satu-satunya kod yang menghuraikan bendera dalam gelung semasa yang tidak berkesudahan. Seterusnya, saya merancang untuk melaksanakan gelung hingga akhir dalam semua program.

Kadang-kadang ini tidak mudah atau berkesan. Kemudian anda perlu menggunakan kelayakan yang tidak menentu. Ia ditentukan apabila pembolehubah diisytiharkan dan memberitahu pengkompil untuk tidak cuba mengoptimumkan penggunaannya. Ia menghalang pengkompil daripada membuat andaian tentang nilai pembolehubah kerana pembolehubah boleh diubah dalam unit program lain, seperti dalam proses selari. Juga, pengkompil meletakkan pembolehubah dalam RAM dan bukannya dalam daftar tujuan umum.

Ia cukup untuk menulis dalam program apabila mengisytiharkan kiraan

kiraan int tidak menentu=0;

dan semua pilihan akan berfungsi.

Untuk atur cara yang mengawal butang, anda mesti mengisytiharkan bahawa sifat suatu contoh kelas Button boleh berubah.

Butang butang meruap1(BUTTON_1_PIN, 15); // penciptaan objek - butang

Menurut pemerhatian saya, menggunakan kelayakan yang tidak menentu tidak meningkatkan panjang kod program dalam apa jua cara.

Perbandingan kaedah pemprosesan isyarat butang dengan perpustakaan Bounce.

Terdapat perpustakaan siap sedia untuk menyahlantun butang Lantunan. Keadaan butang disemak apabila fungsi kemas kini() dipanggil. Dalam fungsi ini:

  • isyarat butang dibaca;
  • berbanding dengan keadaan semasa panggilan sebelumnya untuk mengemas kini();
  • menyemak berapa lama masa telah berlalu sejak panggilan sebelumnya menggunakan fungsi millis();
  • keputusan dibuat sama ada keadaan butang telah berubah.
  • Tetapi ini bukan pemprosesan isyarat selari. Fungsi kemas kini() biasanya dipanggil dalam gelung program asynchronous utama. Jika ia tidak dipanggil lebih lama daripada masa tertentu, maklumat isyarat butang akan hilang. Panggilan tidak teratur membawa kepada operasi algoritma yang salah.
  • Fungsi itu sendiri mempunyai banyak kod dan mengambil masa yang lebih lama untuk dilaksanakan daripada fungsi perpustakaan Button().
  • Tiada penapisan digital bagi isyarat berdasarkan nilai purata sama sekali.

Adalah lebih baik untuk tidak menggunakan perpustakaan ini dalam program yang kompleks.

Dalam pelajaran seterusnya kita akan menulis program yang lebih kompleks dengan proses selari. Kami akan belajar bagaimana untuk melaksanakan pelaksanaan blok program dalam gelung dengan selang masa yang berbeza daripada satu gangguan pemasa.

Kategori: . Anda boleh menanda bukunya.

Pada dasarnya, pemasa mikropengawal ialah kaunter digital, hanya "canggih". Isyarat jam dibekalkan kepada input pembilang, berdasarkan titisan yang mana pembilang meningkatkan nilainya. Apabila peristiwa berlaku - limpahan balas atau nilainya sepadan dengan nilai yang diberikan - permintaan gangguan dijana.

Mari lihat cara menggunakan pemasa T0 dalam mod Normal. Dalam mod ini, pemasa mengira daripada beberapa nilai awal daftar pengiraan kepada maksimum yang mungkin (sehingga 255 atau 0xFF). Apabila pemasa T0 mengira maksimum, maka dalam kitaran jam seterusnya daftar pengiraan TCNT0 melimpah - ia ditetapkan semula dan bendera TOV0 ditetapkan. Jika program membenarkan gangguan secara global (bendera I daftar SREG) dan gangguan limpahan pemasa T0 (bendera TOIE0 daftar TIMSK), maka mikropengawal akan memanggil pengendali yang sepadan. Jika nilai daftar pengiraan bertepatan dengan daftar perbandingan OCR0, maka bendera OCF0 ditetapkan dan jika gangguan acara perlawanan didayakan, pengendalinya akan bermula.

Pemasa T0 dalam mod Biasa

Mari kita pertimbangkan masalah praktikal - kita perlu meninjau butang setiap 20 ms. Kekerapan mikropengawal 8 MHz, mikropengawal ATmega16.

Perkara pertama yang perlu dilakukan ialah memutuskan pilihan pekali praskala pemasa dan mengira nilai awal untuk daftar kaunter TCNT0.

Pemasa T0 boleh dibuat jam daripada isyarat jam dalaman mikropengawal atau dari luar, yang dibekalkan kepada pin T0. Apabila beroperasi daripada isyarat jam dalaman, pengguna boleh memilih nisbah pembahagian frekuensi bagi isyarat ini. Pemasa T0 mempunyai lima pilihan pekali praskala yang mungkin - 1, 8, 64, 256, 1024.

Untuk menyelesaikan masalah ini, saya beralasan seperti berikut. Jika satu tanda pemasa T0 mempunyai tempoh 1 ms, maka ia sesuai dengan saya. 20 kitaran jam memberikan 20 ms. Apakah pekali prascaler pemasa yang akan membolehkan anda mendapatkan tempoh jam hampir 1 ms? Anda boleh mengira.

Kekerapan jam mikropengawal Fcpu = 8000000 Hz
Tempoh jam mikropengawal Tcpu = 1/Fcpu
Tempoh jam pemasa T0 adalah sama dengan Tt0 = (1/Fcpu)/k = k/Fcpu

Pada k = 1024, tempoh jam pemasa T0 akan sama dengan Tt0 = 1024/8000000 = 0.128 ms

Ini ialah tempoh jam pemasa maksimum yang boleh kami perolehi di bawah keadaan kami (Fcpu = 8 MHz). Dengan kemungkinan yang lebih rendah, tempoh tersebut akan menjadi lebih pendek.

Baiklah, okey, katakan satu jam pemasa ialah 0.128 ms, adakah daftar pengiraan cukup lebar untuk mengira selang masa ini dan berapa banyak kitaran jam yang diperlukan? Kami membahagikan selang masa yang diperlukan (20 ms) dengan tempoh satu tanda pemasa dan dapatkan jawapannya.

n = t/Tto = 20 ms/ 0.128 ms = 156.25

Membundarkan kepada keseluruhan terdekat, kita mendapat 156 kitaran jam. Ini kurang daripada 255 (nilai maksimum daftar pengiraan), yang bermaksud bahawa daftar pengiraan TCNT0 adalah mencukupi.

Nilai awal untuk daftar pengiraan TCNT0 dikira sebagai perbezaan antara bilangan maksimum kitaran jam pemasa T0 dan yang diperlukan, iaitu, 256 - 156 = 100. (256 ialah bilangan maksimum selang masa yang mana-mana 8- pemasa bit boleh dikira.)

Saya rasa sekarang sudah jelas cara mengira nilai awal TCNT0 untuk mod Normal:

Kami mengira tempoh satu kitaran pemasa Tt0 = k/Fcpu,
- hitung bilangan kitaran jam yang diperlukan untuk selang waktu n = t/Tto,
- hitung nilai awal untuk daftar pengiraan TCNT0 = 256 - n.

Anda boleh mengautomasikan prosedur ini menggunakan makro. Sebagai contoh, seperti ini:

#define F_CPU 8000000UL
#define TIME_MS(masa, k) (256L - ((masa)*(F_CPU))/(1000L*(k)))

Tetapi dengan makro sedemikian anda perlu berhati-hati; ralat mungkin berlaku pada nilai masa dan k.

Sekarang mari kita beralih kepada kod. Untuk menggunakan pemasa T0 (dan yang lain juga), anda perlu mengkonfigurasinya (memulakan) dan menerangkan pengendali gangguan (jika digunakan).

Memulakan pemasa terdiri daripada langkah berikut:

Hentikan pemasa
- menetapkan mod Normal dalam TCCR0 tanpa permulaan,
- menetapkan nilai awal TCNT0,
- menetapkan semula bendera dalam daftar TIFR,
- dayakan gangguan pada limpahan dalam TIMSK,
- menetapkan praskala dalam TCCR0, iaitu, memulakan pemasa

Variasi mungkin dalam urutan ini.

Untuk tugas kami, kod permulaan akan kelihatan seperti ini:


/*nilai untuk daftar pengiraan*/
#define T_POLL 100

TCCR0 = 0;
TCCR0 = (0<TCNT0 = T_POLL;
TIFR = (1<TIMSK |= (1<TCCR0 |= (1<

Baris permulaan kedua pada dasarnya tidak berguna; ia telah ditambahkan untuk kejelasan. Untuk melihat dengan jelas mod pemasa yang sedang ditetapkan.

Menetapkan semula bendera gangguan dalam daftar TIFR dilakukan dengan menulis 1 pada bit yang sepadan. Operasi ini mesti dilakukan dengan menulis ganti daftar, dan tidak menggunakan bitwise ATAU. Dan inilah sebabnya.

Katakan dua bendera gangguan ditetapkan dalam daftar TIFR - TOV1 dan TOV0. TOV0 kita perlu tetapkan semula. Apabila menetapkan digit yang diperlukan menggunakan ORSesuatu seperti berikut berlaku.


//TIFR mempunyai nilai 0b00000101
//bendera ditetapkan TOV1 dan TOV0
//kod dilaksanakan TIFR |= (1<
//TIFR disalin ke R16
DALAM R16, 0x38

//dalam R16 bit TOV0 ditetapkan
//walaupun ia sudah dipasang
ORI R16, 0x02

//R16 bersamaan dengan 0b00000101 ditulis pada daftar TIFR
KELUAR 0x38, R16

Akibatnya, kedua-dua bendera telah ditetapkan semula, tetapi kami mahu menetapkan semula satu.

Jom sambung.

Sintaks untuk menerangkan pengendali gangguan adalah sedikit berbeza untuk penyusun yang berbeza. Untuk IAR'a, pengendali gangguan pemasa T0 untuk acara limpahan akan kelihatan seperti ini:



{
TCNT0 = T_POLL;

/*perlu ada undian butang di sini*/

TIMER0_OVF_vect ialah alamat vektor gangguan limpahan. Ia diambil daripada fail pengepala pada mikropengawal. Dalam kes ini, saya mengambilnya daripada fail iom16.h.

Baris pertama pengendali (TCNT0 = T_POLL;) menimpa daftar pengiraan dan menetapkan nilai awalnya. Jika ini tidak dilakukan, pemasa akan terus mengira dari 0. Menulis semula daftar pengiraan mesti dilakukan pada permulaan pengendali gangguan.

Semua kod untuk tugas kami akan kelihatan seperti ini. (Kod ditunjukkan untuk IAR. Untuk penyusun lain, anda perlu menukar fail pengepala dan pengendali gangguan.)

#termasuk
#termasuk
#termasuk

#define T_POLL 100

int utama (kosong)
{
/*mulakan pemasa*/

TCCR0 = 0;
TCCR0 = (0<TCNT0 = T_POLL;
TIFR |= (1<TIMSK |= (1<TCCR0 |= (1<

/*mulakan selebihnya peranti*/
DDRB |= (1<

Enable_interrupt();
manakala(1);

/*pengendali sampukan T0
oleh peristiwa limpahan*/
#pragma vector = TIMER0_OVF_vect
__interrupt void TimerT0Ovf(void)
{
/*menimpa daftar pengiraan*/
TCNT0 = T_POLL;

/*butang undian*/

/*penyongsangan PB0 untuk penyahpepijatan*/
PORTB ^= (1<

Kawalan keluaran OC0

Dalam mod Biasa, pemasa T0 boleh menukar keadaan pin OC0 apabila daftar pengiraan dan daftar perbandingan sepadan. Dan walaupun tanpa gangguan. Pilihan kawalan ditentukan oleh bit COM01 dan COM00 daftar TCCR0.

Berikut ialah contoh program yang menjana gelombang persegi pada pin OC0.

#termasuk
#termasuk

int utama (kosong)
{
/*mulakan pemasa T0*/

TCCR0 = 0;
TCCR0 = (0<TCNT0 = 0;
OCR0 = 0;
TIMSK = 0;
TCCR0 |= (1<

/*mulakan OC0*/
DDRB |= (1<

Manakala(1);
pulangan 0;
}

Pin OS0 akan menukar keadaannya kepada sebaliknya apabila daftar pengiraan adalah sifar.

Beberapa perkara tentang menggunakan pemasa

Pengendali gangguan pemasa (dan mana-mana peranti lain) hendaklah dibuat sesingkat mungkin.

Jika nilai yang dikira untuk daftar pengiraan (atau daftar perbandingan) dibundarkan, selang masa akan dikira oleh pemasa dengan ralat.

Dan satu perkara terakhir. Ia mungkin berlaku bahawa pemprosesan gangguan pemasa ditangguhkan (contohnya, disebabkan oleh kesalahan pengendali lain) dan daftar TCNT0 sudah akan mengira beberapa kitaran jam. Jika anda hanya menulis ganti nilai TCNT0, maka gangguan seterusnya akan dipanggil lewat daripada yang diperlukan. Ternyata gangguan sebelumnya (tertunda) dan baru tidak akan menahan selang yang diperlukan.

Keadaan ini boleh diselesaikan jika anda menulis ganti daftar pengiraan seperti ini:

TCNT0 = TCNT0 + startValue;

Menambah nilai semasa daftar pengiraan dengan yang dimulakan akan mengambil kira kitaran jam tambahan ini.Memang ada satu TETAPI! Jika startValue besar, operasi penambahan boleh menyebabkan daftar kaunter melimpah.

Sebagai contoh, startValue = 250, dan pemasa berjaya mengira hingga 10. Kemudian operasi penambahan akan membawa kepada hasil berikut:

10 + 250 = 260

Kami mengambil 8 digit daripada 260 dan mendapat 4. 4 ditulis kepada TCNT0.

Gangguan membolehkan mikropengawal bertindak balas kepada peristiwa tanpa perlu sentiasa menyemak sebarang keadaan untuk menentukan apabila perubahan penting telah berlaku. Selain keupayaan untuk menyambungkan sumber gangguan kepada beberapa pin, anda juga boleh menggunakan gangguan yang dijana oleh pemasa.

Perkakasan terganggu

Untuk menunjukkan penggunaan sampukan, mari kembali kepada input digital. Selalunya, untuk menentukan momen beberapa peristiwa input (contohnya, menekan butang), kod berikut digunakan:

if (digitalRead(inputPin) == LOW)

// Lakukan beberapa tindakan

Kod ini sentiasa menyemak tahap voltan pada inputPin, dan apabila digitalRead mengembalikan LOW, ia melakukan sesuatu, ditunjukkan oleh komen // Lakukan sesuatu. Ini adalah penyelesaian yang boleh dilaksanakan sepenuhnya, tetapi bagaimana jika terdapat banyak operasi lain yang perlu dilakukan di dalam fungsi gelung? Semua operasi ini mengambil masa, jadi ada kemungkinan terlepas tekan butang pendek semasa pemproses sibuk dengan sesuatu yang lain. Malah, hampir mustahil untuk terlepas fakta menekan butang, kerana mengikut piawaian mikropengawal ia tetap ditekan untuk masa yang sangat lama.

Tetapi bagaimana pula dengan denyutan pendek dari sensor, yang boleh bertahan sepersejuta saat? Untuk menerima acara sedemikian, anda harus menggunakan gangguan, menentukan fungsi yang akan dipanggil pada acara ini, tanpa mengira apa yang dilakukan oleh mikropengawal. Gangguan sedemikian dipanggil gangguan perkakasan(perkakasan terganggu).

Dalam Arduino Uno, hanya dua pin yang dikaitkan dengan gangguan perkakasan, itulah sebabnya ia digunakan dengan sangat jarang. Leonardo mempunyai lima daripada pin ini, papan yang lebih besar seperti Mega2560 mempunyai banyak lagi, dan pin Due semuanya berkeupayaan gangguan.

Berikut menerangkan cara gangguan perkakasan berfungsi. Untuk mencuba contoh yang diberikan, anda memerlukan papan roti tambahan, butang, perintang 1k ohm dan beberapa wayar pelompat.

Dalam Rajah. 3.1 menunjukkan litar yang dipasang. Melalui rintangan, voltan TINGGI dikenakan pada pin D2 sehingga butang ditekan, di mana titik pin D2 akan dibumikan dan paras voltan padanya akan turun kepada RENDAH.

Muat naik lakaran berikut ke papan Arduino anda:

// lakaran 03_01_interrupts

int ledPin = 13;

pinMode(ledPin, OUTPUT);

void stuffHapenned()

digitalWrite(ledPin, HIGH);

nasi. 3.1. Gambar rajah litar untuk ujian gangguan

Selain menetapkan pin LED untuk beroperasi sebagai output digital, fungsi persediaan menggunakan baris lain untuk mengaitkan fungsi dengan gangguan. Sekarang fungsi ini akan dipanggil secara automatik sebagai tindak balas kepada setiap gangguan. Mari kita lihat lebih dekat pada baris ini, kerana argumen untuk fungsi yang dipanggil di sini kelihatan agak luar biasa:

attachInterrupt(0, stuffHapenned, FALLING);

Argumen pertama - 0 - ialah nombor gangguan. Ia akan menjadi lebih jelas jika nombor gangguan itu bertepatan dengan nombor pin, tetapi ini tidak berlaku. Dalam Arduino Uno, Interrupt 0 dikaitkan dengan pin D2 dan Interrupt 1 dikaitkan dengan pin D3. Keadaan menjadi lebih mengelirukan kerana fakta bahawa dalam model Arduino lain gangguan ini dikaitkan dengan pin yang berbeza, dan sebagai tambahan, dalam Arduino Due anda perlu menentukan nombor pin. Pada papan Arduino Due, semua pin dikaitkan dengan gangguan.

Saya akan kembali kepada masalah ini kemudian, tetapi buat masa ini mari kita beralih kepada hujah kedua. Hujah ini, stuffHappened, mewakili nama fungsi yang harus dipanggil untuk mengendalikan gangguan. Fungsi ini ditakrifkan lagi dalam lakaran. Fungsi sedemikian dipanggil mengganggu rutin(Rutin Perkhidmatan Interrupt, ISR), terdapat keperluan khas. Mereka tidak boleh mempunyai parameter dan tidak boleh mengembalikan apa-apa. Ini agak masuk akal: walaupun mereka dipanggil di tempat yang berbeza dalam lakaran, tidak ada satu baris kod yang memanggil ISR secara langsung, jadi tidak ada cara untuk menghantar parameter kepada mereka atau mendapatkan nilai pulangan.

Parameter terakhir fungsi, attachInterrupt, adalah pemalar, dalam kes ini JATUH. Ini bermakna bahawa rutin gangguan akan dipanggil hanya apabila voltan pada pin D2 berubah dari tahap TINGGI ke tahap RENDAH (iaitu, apabila jatuh), yang berlaku apabila butang ditekan.

Perhatikan bahawa tiada kod dalam fungsi gelung. Secara umum, fungsi ini mungkin mengandungi kod yang sedang dilaksanakan sehingga gangguan berlaku. Rutin gangguan itu sendiri hanya menghidupkan LED L.

Apabila anda bereksperimen, selepas menetapkan semula Arduino, LED L harus dimatikan. Dan selepas menekan butang, ia akan serta-merta menyala dan kekal menyala sehingga penetapan semula seterusnya.

Selepas mencuba, cuba tukar hujah terakhir dalam panggilan attachInterrupt kepada RISING dan muat naik lakaran yang diubah suai. Selepas memulakan semula Arduino, LED harus kekal mati, kerana voltan pada pin, walaupun pada tahap TINGGI, kekal pada tahap ini sejak dimulakan semula. Sehingga saat ini, voltan pada sesentuh tidak turun ke tahap RENDAH dan kemudian naik (meningkat) ke tahap TINGGI.

Sebaik sahaja anda menekan dan menahan butang, LED harus kekal mati sehingga anda melepaskannya. Melepaskan butang akan menyebabkan gangguan yang dikaitkan dengan pin D2 kerana semasa butang ditekan, paras voltan pada pin adalah RENDAH, dan apabila dilepaskan ia meningkat kepada TINGGI.

Jika semasa ujian ternyata apa yang berlaku kepada anda tidak sesuai dengan penerangan yang diberikan sebelum ini, kemungkinan besar ini disebabkan oleh kesan melantun kenalan dalam butang. Kesan ini disebabkan oleh fakta bahawa butang tidak memberikan peralihan yang jelas antara keadaan "hidup" dan "mati" sebaliknya, pada saat menekan, terdapat peralihan berulang antara keadaan ini sehingga keadaan "hidup". tetap. Cuba tekan butang dengan lebih kuat, ini sepatutnya membantu mendapatkan peralihan yang jelas antara keadaan tanpa kesan lantunan.

Satu lagi cara untuk mencuba lakaran ini ialah dengan menekan dan menahan butang sambil menekan dan melepaskan butang Reset pada papan Arduino. Kemudian, apabila lakaran bermula, lepaskan butang pada papan roti dan LED L akan menyala.

Pin didayakan gangguan

Mari kembali sekarang kepada masalah penamaan gangguan. Dalam jadual 3.1 menyenaraikan model papan Arduino yang paling biasa dan menunjukkan korespondensi bilangan gangguan dan kenalan di dalamnya.

Jadual 3.1. Pin didayakan gangguan dalam model Arduino yang berbeza

Model Nombor gangguan Nota
0 1 2 3 4 5
Uno D2 D3 - - - -
Leonardo D3 D2 D0 D1 D7 - Malah, berbanding dengan Uno, dua sampukan pertama diberikan kepada pin yang berbeza
Mega2560 D2 D3 D21 D20 D19 D18
kena bayar - - - - - - Daripada nombor sampukan, fungsi attachInterrupt harus diberikan nombor pin

Menukar pin dua sampukan pertama dalam Uno dan Leonardo mencipta perangkap yang mudah untuk jatuh ke dalamnya. Dalam model Due, bukannya nombor sampukan, fungsi attachInterrupt harus dihantar nombor pin, yang kelihatan lebih logik.

Mod gangguan

Mod sampukan RISING (rising edge) dan FALLING (falling edge) yang digunakan dalam contoh sebelumnya adalah yang paling kerap digunakan dalam amalan. Walau bagaimanapun, terdapat beberapa mod lain. Mod ini disenaraikan dan diterangkan dalam Jadual. 3.2.

Jadual 3.2. Mod gangguan

Mod Tindakan Penerangan
RENDAH Gangguan dijana pada tahap voltan RENDAH Dalam mod ini, rutin gangguan akan dipanggil secara berterusan selagi pin kekal rendah.
MENINGKAT Gangguan dijana apabila voltan turun positif, dari RENDAH ke TINGGI. -
JATUH Gangguan dijana pada penurunan voltan negatif, dari TINGGI ke RENDAH. -
TINGGI Gangguan dijana pada tahap voltan TINGGI Mod ini hanya disokong dalam model Arduino Due dan, seperti mod LOW, jarang digunakan dalam amalan.

Dayakan impedans dalaman

Litar dalam contoh sebelumnya menggunakan perintang tarik luar. Walau bagaimanapun, dalam praktiknya, isyarat penyebab gangguan sering dipacu daripada output digital penderia, dalam hal ini tidak perlu menggunakan perintang tarik naik.

Tetapi jika peranan sensor dimainkan oleh butang yang disambungkan dengan cara yang sama seperti papan roti dalam Rajah. 3.1, adalah mungkin untuk menyingkirkan rintangan dengan menghidupkan rintangan "pull-up" dalaman dengan nilai nominal kira-kira 40 kOhm. Untuk melakukan ini, anda mesti menetapkan mod INPUT_PULLUP secara eksplisit untuk pin berkaitan gangguan, seperti yang ditunjukkan dalam baris dalam huruf tebal:

pinMode(ledPin, OUTPUT);

pinMode(2, INPUT_PULLUP);

attachInterrupt(0, stuffHapenned, FALLING);

Mengganggu rutin

Kadangkala nampaknya keupayaan untuk mengendalikan gangguan semasa fungsi gelung sedang berjalan menyediakan cara mudah untuk mengendalikan acara seperti ketukan kekunci. Tetapi pada hakikatnya terdapat sekatan yang sangat ketat terhadap perkara yang boleh dan tidak boleh dilakukan oleh rutin mengganggu.

Rutin gangguan hendaklah sesingkat dan sepantas mungkin. Jika gangguan lain berlaku semasa rutin gangguan sedang berjalan, rutin tidak akan terganggu dan isyarat yang terhasil akan diabaikan begitu sahaja. Ini bermakna, sebagai contoh, jika sampukan digunakan untuk mengukur kekerapan, anda mungkin mendapat nilai yang salah.

Selain itu, semasa rutin gangguan berjalan, kod dalam fungsi gelung adalah melahu.

Gangguan dilumpuhkan secara automatik semasa pemprosesan. Penyelesaian ini menghalang kekeliruan antara subrutin yang mengganggu satu sama lain, tetapi mempunyai kesan sampingan yang tidak diingini. Fungsi kelewatan menggunakan pemasa dan gangguan, jadi ia tidak akan berfungsi dalam rutin gangguan. Perkara yang sama berlaku untuk fungsi millis. Cuba menggunakan millis untuk mendapatkan bilangan milisaat yang telah berlalu sejak papan kali terakhir ditetapkan semula untuk melakukan kelewatan dengan cara ini tidak akan berjaya, kerana ia akan mengembalikan nilai yang sama sehingga rutin gangguan selesai. Walau bagaimanapun, anda boleh menggunakan fungsi delayMicroseconds, yang tidak menggunakan gangguan.

Gangguan juga digunakan dalam komunikasi bersiri, jadi jangan cuba gunakan Serial.print atau fungsi baca port bersiri. Walau bagaimanapun, anda boleh mencuba, dan kadang-kadang mereka akan berfungsi, tetapi jangan mengharapkan kebolehpercayaan yang tinggi daripada sambungan sedemikian.

Pembolehubah Operasi

Memandangkan rutin gangguan tidak boleh mempunyai parameter dan tidak dapat mengembalikan apa-apa, beberapa cara untuk menghantar maklumat antaranya dan seluruh program diperlukan. Biasanya, pembolehubah global digunakan untuk ini, seperti yang ditunjukkan dalam contoh berikut:

// lakaran 03_02_interrupt_flash

int ledPin = 13;

kilat boolean meruapFast = palsu;

pinMode(ledPin, OUTPUT);

attachInterrupt(0, stuffHapenned, FALLING);

tempoh int = 1000;

jika (flashFast) tempoh = 100;

digitalWrite(ledPin, HIGH);

digitalWrite(ledPin, LOW);

void stuffHapenned()

kilatFast = ! flashFast;

Dalam lakaran ini, fungsi gelung menggunakan flashFast pembolehubah global untuk menentukan tempoh kelewatan. Rutin pemprosesan mengubah nilai pembolehubah ini antara benar dan salah.

Ambil perhatian bahawa pengisytiharan pembolehubah flashFast termasuk perkataan yang tidak menentu. Anda boleh berjaya membangunkan lakaran tanpa penentu yang tidak menentu, tetapi ia amat diperlukan kerana tanpanya, pengkompil C boleh menjana kod mesin yang menyimpan cache nilai pembolehubah dalam daftar untuk meningkatkan prestasi. Jika, seperti dalam kes ini, kod caching terganggu, ia mungkin tidak menyedari perubahan dalam nilai pembolehubah.

Kesimpulannya tentang rutin gangguan

Apabila anda menulis rutin gangguan, ingat peraturan berikut.

Subrutin mesti bertindak cepat.

Untuk memindahkan data antara rutin gangguan dan seluruh program, pembolehubah yang diisytiharkan dengan penentu yang tidak menentu mesti digunakan.

Jangan gunakan kelewatan, tetapi anda boleh menggunakan delayMicroseconds.

Jangan mengharapkan komunikasi yang sangat dipercayai melalui port bersiri.

Jangan mengharapkan nilai yang dikembalikan oleh fungsi millis akan berubah.

Dayakan dan lumpuhkan gangguan

Secara lalai, gangguan didayakan dalam lakaran dan, seperti yang dinyatakan sebelum ini, dilumpuhkan secara automatik semasa rutin gangguan sedang berjalan. Walau bagaimanapun, adalah mungkin untuk melumpuhkan dan mendayakan gangguan secara eksplisit dalam kod program dengan memanggil fungsi noInterrupts dan interrupts. Fungsi ini tidak mempunyai parameter, dan yang pertama menyahdayakan gangguan, dan yang kedua membolehkannya.

Kawalan eksplisit mungkin diperlukan untuk memastikan bahawa sekeping kod, seperti yang mengeluarkan jujukan data atau menjana jujukan denyutan dan dimasa dengan tepat menggunakan fungsi delayMicroseconds, tidak boleh diganggu.

Pemasa menyampuk

Panggilan rutin pengendalian gangguan boleh dianjurkan bukan sahaja oleh acara luaran, tetapi juga oleh peristiwa perubahan masa dalaman. Ciri ini amat berguna apabila anda perlu melakukan operasi tertentu pada selang waktu tertentu.

Pustaka TimerOne memudahkan untuk mengkonfigurasi gangguan pemasa. Ia boleh didapati dan dimuat turun di http://playground.arduino.cc/Code/Timer1.

Contoh berikut menunjukkan cara menggunakan TimerOne untuk menjana kereta api nadi gelombang persegi 1 kHz. Jika anda mempunyai osiloskop atau multimeter dengan keupayaan untuk mengukur kekerapan, sambungkannya ke pin 12 untuk melihat isyarat (Gamb. 3.2).

nasi. 3.2. Urutan nadi segi empat tepat dijana menggunakan pemasa

// lakaran_03_03_1kHz

#termasuk

int outputPin = 12;

keluaran int tidak menentu = RENDAH;

pinMode(12, OUTPUT);

Pemasa1.memulakan(500);

Pemasa1.attachInterrupt(toggleOutput);

void toggleOutput()

digitalWrite(outputPin, output);

keluaran = ! keluaran;

Perkara yang sama boleh dilaksanakan menggunakan kelewatan, tetapi penggunaan gangguan pemasa membolehkan anda mengatur pelaksanaan sebarang operasi lain di dalam gelung. Di samping itu, menggunakan fungsi kelewatan tidak akan mencapai ketepatan yang tinggi, kerana masa yang diperlukan untuk menukar tahap voltan pada kenalan tidak akan diambil kira dalam nilai kelewatan.

NOTA

Semua sekatan untuk rutin gangguan luaran yang telah dibincangkan sebelum ini juga digunakan untuk rutin gangguan pemasa.

Menggunakan kaedah yang dibentangkan, anda boleh menetapkan sebarang selang antara gangguan dalam julat dari 1 hingga 8,388,480 μs, iaitu, sehingga lebih kurang 8.4 s. Nilai selang dihantar ke fungsi permulaan dalam mikrosaat.

Pustaka TimerOne juga memungkinkan untuk menggunakan pemasa untuk menjana isyarat Modulasi Lebar Nadi (PWM) pada pin 9 dan 10 papan. Ini mungkin kelihatan seperti berlebihan kerana analogWrite melakukan perkara yang sama, tetapi menggunakan gangguan membolehkan kawalan isyarat PWM yang lebih tepat. Khususnya, menggunakan pendekatan ini, adalah mungkin untuk mengatur ukuran panjang nadi positif dalam julat 0...1023 dan bukannya 0...255 dalam fungsi analogWrite. Di samping itu, apabila menggunakan analogWrite, kadar pengulangan nadi dalam isyarat PWM ialah 500 Hz, dan menggunakan TimerOne anda boleh menambah atau mengurangkan frekuensi ini.

Untuk menjana isyarat PWM menggunakan perpustakaan TimerOne, gunakan fungsi Timer1.pwm, seperti ditunjukkan dalam contoh berikut:

// sketsa_03_04_pwm

#termasuk

pinMode(9, OUTPUT);

pinMode(10, OUTPUT);

Pemasa1.memulakan(1000);

Pemasa1.pwm(9, 512);

Pemasa1.pwm(10, 255);

Di sini tempoh ulangan nadi dipilih menjadi 1000 μs, iaitu frekuensi isyarat PWM ialah 1 kHz. Dalam Rajah. 3.3 menunjukkan bentuk gelombang pada pin 10 ( naik) dan 9 ( turun).

nasi. 3.3. Isyarat lebar nadi 1 kHz dijana menggunakan TimerOne

Sekadar suka-suka, mari kita lihat sejauh mana frekuensi isyarat PWM boleh ditingkatkan. Jika panjang tempoh dikurangkan kepada 10, frekuensi isyarat PWM harus meningkat kepada 100 kHz. Bentuk gelombang yang diperoleh dengan parameter ini ditunjukkan dalam Rajah. 3.4.

Walaupun terdapat herotan sementara yang ketara, yang agak dijangka, panjang denyutan positif masih kekal hampir 25 dan 50%, masing-masing.

nasi. 3.4. Isyarat lebar nadi 100 kHz dijana menggunakan TimerOne

Kesimpulannya

Gangguan, walaupun kadangkala dilihat sebagai penyelesaian ideal untuk projek yang sukar, boleh menyukarkan kod untuk nyahpepijat dan bukan selalunya cara terbaik untuk menyelesaikan masalah yang sukar. Pertimbangkan penyelesaian yang mungkin dengan teliti sebelum memberi komitmen kepada mereka. Dalam Bab 14, kita akan melihat helah lain untuk mengatasi kesukaran ketidakupayaan Arduino untuk mengendalikan lebih daripada satu tugas pada satu masa.

Kami akan kembali kepada gangguan dalam Bab 5, di mana kami akan melihat bagaimana ia boleh digunakan untuk mengurangkan penggunaan kuasa papan Arduino dengan meletakkannya secara berkala ke dalam mod penjimatan kuasa, dan dalam Bab 13, di mana kami akan menggunakan sampukan untuk meningkatkan ketepatan pemprosesan isyarat digital.

Dalam bab seterusnya, kami akan meneroka teknik untuk memaksimumkan prestasi Arduino.

Kami mengetahui kaunter lelaran gelung utama dan mendapati bahawa ia tidak sesuai sama sekali untuk bacaan masa yang tepat - kelajuan pengatup terapung, dan sukar untuk mengiranya. Apa yang perlu dilakukan?

Jelas sekali, kami memerlukan sejenis kaunter luaran yang akan berdetik tanpa mengira operasi pemproses, dan pemproses boleh pada bila-bila masa melihat apa yang berdetik di dalamnya. Atau untuk kaunter menjana peristiwa limpahan atau aliran bawah - naikkan bendera atau jana gangguan. Dan peratusan akan menghidunya dan memprosesnya.

Dan terdapat kaunter sebegitu, bukan satu pun - ini adalah pemasa persisian. Mungkin terdapat beberapa daripadanya dalam AVR, malah dengan kedalaman bit yang berbeza. ATmega16 ada tiga, ATmega128 ada empat. Dan dalam MK baharu siri AVR mungkin terdapat lebih banyak lagi, saya tidak mengenalinya.

Lebih-lebih lagi, pemasa boleh menjadi lebih daripada sekadar kaunter bodoh; pemasa ialah salah satu peranti persisian yang paling canggih (dari segi fungsi alternatif).

Apa yang boleh dilakukan oleh pemasa?

  • Tandakan pada kelajuan yang berbeza, mengira masa
  • Kira denyutan masuk dari luar (mod kaunter)
  • Tandakan dari kuarza luaran pada 32768Hz
  • Hasilkan beberapa jenis isyarat PWM
  • Isu mengganggu (setengah dozen acara berbeza) dan menetapkan bendera

Pemasa yang berbeza mempunyai fungsi yang berbeza dan kedalaman bit yang berbeza. Lihat lembaran data untuk butiran lanjut.

Sumber tick pemasa
Pemasa/Kaunter (selepas ini saya akan memanggilnya T/C) mengira sama ada denyutan jam daripada penjana jam terbina dalam atau daripada input mengira.

Lihat dengan teliti pada pinout kaki ATmega16, adakah anda melihat kaki T1 dan T0 di sana?

Jadi ini adalah input pengiraan Pemasa 0 dan Pemasa 1. Dengan tetapan yang sesuai, T/S akan mengira sama ada tepi hadapan (tepi dari 0-1) atau tepi mengekor (tepi 1-0) bagi denyutan yang tiba pada input ini.

Perkara utama ialah kekerapan denyutan masuk tidak melebihi kekerapan jam pemproses, jika tidak, ia tidak akan mempunyai masa untuk memproses denyutan.

Di samping itu, T/C2 mampu beroperasi dalam mod tak segerak. Iaitu, T/S tidak mengira denyutan jam pemproses, mahupun denyutan masuk ke kaki, tetapi denyutan pengayunnya sendiri, dikuasakan oleh kuarza yang berasingan. Untuk melakukan ini, T/C2 mempunyai input TOSC1 dan TOSC2, di mana anda boleh memasang resonator kuarza.

Mengapa ini perlu? Ya, sekurang-kurangnya atur jam masa sebenar. Saya menggantung kuarza jam pada mereka pada 32768 Hz dan mengira masa - 128 limpahan akan berlaku sesaat (kerana T/C2 ialah lapan bit). Jadi satu limpahan ialah 1/128 saat. Selain itu, pemasa tidak berhenti semasa gangguan limpahan sedang diproses; Jadi jam adalah angin!

Predivider
Jika pemasa mengira denyutan daripada penjana jam, atau dari dalamannya, maka ia masih boleh disalurkan melalui praskala.

Iaitu, sebelum memasuki daftar pengiraan, kekerapan nadi akan dibahagikan. Anda boleh membahagi dengan 8, 32, 64, 128, 256, 1024. Jadi jika anda meletakkan kuarza jam pada T/C2 dan melepasinya melalui praskala pada 128, maka pemasa anda akan berdetik pada kelajuan satu detik sesaat.

Selesa! Ia juga mudah untuk menggunakan prescaler apabila anda hanya perlu mendapatkan selang yang besar, dan satu-satunya sumber kutu adalah penjana jam pemproses pada 8 MHz, anda akan bosan mengira megahertz ini, tetapi jika anda meneruskannya melalui prascaler , pada 1024, maka semuanya lebih bahagia.

Tetapi terdapat satu keanehan di sini, hakikatnya ialah jika kita melancarkan T/S dengan sejenis prascaler yang kejam, contohnya pada 1024, maka tanda pertama pada daftar pengiraan tidak semestinya akan datang selepas 1024 nadi.

Ia bergantung pada keadaan praskala itu, bagaimana jika pada masa kita menghidupkannya ia sudah dikira hampir 1024? Ini bermakna akan ada tanda segera. Praskala berfungsi sepanjang masa, tidak kira sama ada pemasa dihidupkan atau tidak.

Oleh itu, praskala boleh dan harus ditetapkan semula. Anda juga perlu mengambil kira hakikat bahawa praskala adalah sama untuk semua kaunter, jadi apabila menetapkannya semula, anda perlu mengambil kira hakikat bahawa pemasa lain akan kehilangan masa sehingga tanda seterusnya, dan ia boleh menjadi salah dengan tepat. dengan cara ini.

Sebagai contoh, pemasa pertama beroperasi pada pin 1:64, dan yang kedua pada pin 1:1024 prascaler. Yang kedua hampir mencapai 1024 dalam praskala dan kini sepatutnya ada tanda pemasa, tetapi kemudian anda pergi dan menetapkan semula praskala untuk memulakan pemasa pertama tepat dari awal. Apa yang akan berlaku? Betul, pembahagi kedua akan segera menetapkan semula kepada 0 (prescaler adalah sama, ia mempunyai satu daftar) dan pemasa kedua perlu menunggu 1024 kitaran jam lagi untuk mendapatkan impuls yang diingini!

Dan jika anda menetapkan semula praskala dalam gelung, untuk faedah pemasa pertama, lebih kerap daripada sekali setiap 1024 kitaran jam, maka pemasa kedua tidak akan berdetik, dan anda akan memukul kepala anda di atas meja, cuba memahami sebabnya pemasa kedua anda tidak berfungsi, walaupun mesti.

Untuk menetapkan semula praskala, hanya tulis bit PSR10 dalam daftar SFIOR. Bit PSR10 akan ditetapkan semula secara automatik pada kitaran jam seterusnya.

Daftar akaun
Keseluruhan hasil siksaan yang diterangkan di atas terkumpul dalam daftar pengiraan TCNTx, dengan x ialah nombor pemasa. ia boleh sama ada lapan-bit atau enam belas-bit, di mana ia terdiri daripada dua daftar TCNTxH dan TCNTxL - bait tinggi dan rendah, masing-masing.

Dan ada tangkapan di sini, jika anda perlu meletakkan nombor dalam daftar lapan bit, maka tidak ada masalah OUT TCNT0, Rx dan tiada paku, maka dengan daftar dua bait anda perlu bermain-main.

Dan keseluruhannya ialah pemasa mengira secara bebas daripada pemproses, jadi kita boleh meletakkan satu bait dahulu, ia akan mula mengira, kemudian yang kedua, dan pengiraan semula akan mula mengambil kira bait kedua.

Adakah anda berasa seperti saya bergaul? Di sini! Pemasa ialah peranti yang tepat, jadi daftar pengiraannya mesti dimuatkan pada masa yang sama! Tetapi bagaimana? Dan jurutera dari Atmel menyelesaikan masalah itu dengan mudah:
Daftar tinggi (TCNTxH) ditulis pertama dalam daftar TEMP. Daftar ini adalah rasmi semata-mata dan sama sekali tidak boleh diakses oleh kami.

Apa yang kita hadapi: Kami menulis bait tinggi ke daftar TEMP (bagi kami ini adalah satu neraka TCNTxH), dan kemudian menulis bait rendah. Pada masa ini, nilai yang kami rakamkan sebelum ini dimasukkan ke dalam TCNTxH sebenar. Iaitu, dua bait, tinggi dan rendah, ditulis serentak! Anda tidak boleh menukar pesanan! Itu sahaja caranya

Ia kelihatan seperti ini:

CLI ; Kami melarang gangguan, tanpa gagal!

KELUAR TCNT1H,R16 ; Bait yang paling ketara ditulis dahulu kepada TEMP OUT TCNT1L,R17 ; Dan sekarang saya telah mendaftar untuk kedua-dua kelas senior dan junior!

SEI; Dayakan gangguan

Mengapa melumpuhkan gangguan? Ya, supaya selepas menulis bait pertama, program itu tidak secara tidak sengaja tergesa-gesa tanpa gangguan, dan kemudian seseorang merogol pemasa kami. Kemudian dalam daftarnya ia tidak akan menjadi apa yang kami hantar ke sini (atau dalam gangguan), tetapi apa yang berlaku. Jadi cuba tangkap pepijat seperti itu kemudian! Tetapi ia boleh keluar pada saat yang paling tidak sesuai, tetapi anda tidak akan menangkapnya, kerana gangguan hampir merupakan pembolehubah rawak. Jadi detik sebegini perlu ditangani segera.
Saya tidak akan menerangkan semua fungsi pemasa, jika tidak, ia akan menjadi risalah yang luar biasa. Lebih baik bercakap tentang yang utama - yang dikira, dan semua jenis PWM dan penjana lain akan berada dalam artikel lain. Jadi bersabarlah, atau kunyah lembaran data, ia juga berguna.

Jadi daftar utama ialah TCCRx
Untuk T/C0 dan T/C2 ini adalah TCCR0 dan TCCR2, masing-masing, dan untuk T/C1 ini adalah TCCR1B

Buat masa ini, kami hanya berminat dengan tiga bit pertama daftar ini:
CSx2.. CSx0, gantikan x dengan nombor pemasa.
Mereka bertanggungjawab untuk menetapkan prescaler dan sumber jam.

Pemasa yang berbeza sedikit berbeza, jadi saya akan menerangkan bit CS02..CS00 sahaja untuk pemasa 0

  • 000 - pemasa berhenti
  • 001 — praskala adalah sama dengan 1, iaitu, padam. pemasa mengira denyutan jam
  • 010 - praskala ialah 8, kekerapan jam dibahagikan dengan 8
  • 011 - praskala ialah 64, kekerapan jam dibahagikan dengan 64
  • 100 - praskala ialah 256, kekerapan jam dibahagikan dengan 256
  • 101 - praskala ialah 1024, kekerapan jam dibahagikan dengan 1024
  • 110 - denyutan jam datang dari pin T0 pada peralihan dari 1 ke 0
  • 111 - denyutan jam datang dari pin T0 pada peralihan dari 0 ke 1

menyampuk
Setiap acara perkakasan mempunyai gangguan, dan pemasa tidak terkecuali. Sebaik sahaja limpahan atau beberapa peristiwa aneh lain berlaku, gangguan serta-merta muncul.

Daftar TIMSK dan TIFR bertanggungjawab untuk gangguan daripada pemasa. Dan AVR yang lebih sejuk, seperti ATMega128, juga mempunyai ETIFR dan ETIMSK - sejenis kesinambungan, kerana akan ada lebih banyak pemasa di sana.

TIMSK ialah daftar topeng. Iaitu, bit yang terkandung di dalamnya membolehkan gangguan setempat. Jika bit ditetapkan, gangguan khusus didayakan. Jika bit adalah sifar, maka gangguan ini ditutup dengan lembangan. Secara lalai, semua bit adalah sifar.

Pada masa ini kami hanya berminat dengan gangguan limpahan. Bit bertanggungjawab untuk mereka

  • TOIE0 - kebenaran untuk mengganggu pada pemasa 0 limpahan
  • TOIE1 - kebenaran untuk mengganggu pada limpahan pemasa 1
  • TOIE2 - kebenaran untuk mengganggu pada limpahan pemasa 2

Kita akan bercakap tentang ciri lain dan gangguan pemasa kemudian, apabila kita melihat PWM.

Daftar TIFR secara langsung adalah daftar bendera. Apabila beberapa gangguan dicetuskan, bendera muncul yang menunjukkan bahawa kami mengalami gangguan. Bendera ini ditetapkan semula oleh perkakasan apabila program meninggalkan vektor. Jika gangguan dilumpuhkan, maka bendera akan kekal di sana sehingga gangguan didayakan dan program pergi ke gangguan.

Untuk mengelakkan ini daripada berlaku, bendera boleh ditetapkan semula secara manual. Untuk melakukan ini, anda perlu menulis 1 dalam daftar TIFR!

Sekarang mari kita bercinta
Baiklah, mari kita reka bentuk semula program untuk berfungsi dengan pemasa. Mari perkenalkan pemasa program. Organ tong akan kekal begitu, biarkan ia berdetik. Dan kami akan menambah pembolehubah kedua, juga empat bait:

ORG $010 RETI ; (TIMER1 OVF) Pemasa/Counter1 Limpahan .ORG $012 RJMP Timer0_OV ; (TIMER0 OVF) Pemasa/Counter0 Limpahan .ORG $014 RETI ; (SPI,STC) Pemindahan Bersiri Selesai

Mari tambahkan pengendali gangguan untuk limpahan pemasa 0 ke bahagian Gangguan. Memandangkan makro berdetik kami berfungsi secara aktif dengan daftar dan merosakkan bendera, kami perlu menyimpan keseluruhan perkara ini pada timbunan dahulu:

Dengan cara ini, mari kita cipta satu lagi makro yang menolak daftar bendera SREG ke dalam timbunan dan yang kedua yang mengambilnya dari sana.

1 2 3 4 5 6 7 8 9 10 11 12 .MACRO PUSHF PUSH R16 DALAM R16,SREG PUSH R16 .ENDM .MACRO POPF POP R16 OUT SREG,R16 POP R16 .ENDM

MAKRO PUSHF PUSH R16 DALAM R16,SREG PUSH R16 .ENDM .MACRO POPF POP R16 KELUAR SREG,R16 POP R16 .ENDM

Sebagai kesan sampingan, ia juga mengekalkan R16, ingat itu :)

1 2 3 4 5 6 7 8 9 10 11 12 13 Pemasa0_OV: PUSHF PUSH R17 PUSH R18 PUSH R19 INCM TCNT POP R19 POP R18 POP R17 POPF RETI

Pemasa0_OV: PUSHF PUSH R17 PUSH R18 PUSH R19 INCM TCNT POP R19 POP R18 POP R17 POPF RETI

Sekarang mulakan pemasa. Tambahkannya pada bahagian Init Perkakasan Dalaman.

; Init Perkakasan Dalaman ======================================= SETB DDRD,4,R16 ; DDRD.4 = 1 SETB DDRD,5,R16 ; DDRD.5 = 1 SETB DDRD,7,R16 ; DDRD.7 = 1 SETB PORTD,6,R16 ; Output PD6 ke input tarik-up CLRB DDRD,6,R16 ; Untuk membaca butang SETB TIMSK,TOIE0,R16 ; Dayakan gangguan pemasa OUTI TCCR0,1<

Apa yang tinggal ialah menulis semula blok perbandingan kami dan mengira semula nombornya. Sekarang semuanya mudah, satu tanda satu bar. Tanpa sebarang masalah dengan panjang kod yang berbeza. Untuk satu saat pada 8 MHz, 8 juta kutu mesti dibuat. Dalam heks ini ialah 7A 12 00, dengan mengambil kira bahawa bait rendah ialah TCNT0, maka 7A 12 ditinggalkan untuk kaunter kami dan juga dua bait tertinggi 00 00, ia tidak perlu disemak. Tidak perlu menutup; kami akan menetapkan semula pemasa kemudian.

Terdapat hanya satu masalah - bait rendah, satu dalam pemasa. Ia menandakan setiap tanda dan hampir mustahil untuk menyemak pematuhan. Kerana percanggahan yang sedikit dan keadaan perbandingan akan muncul dalam NoMatch, tetapi untuk menekanya supaya semakan nilainya bertepatan dengan langkah tertentu ini... Lebih mudah untuk menarik jarum keluar dari timbunan jerami pada percubaan pertama secara rawak.

Jadi ketepatan dalam kes ini adalah terhad - anda perlu mempunyai masa untuk menyemak nilai sebelum ia meninggalkan julat. Dalam kes ini, julat adalah, untuk kesederhanaan, 255 - nilai bait rendah, nilai dalam pemasa.

Kemudian kedua kami disediakan dengan ketepatan 8,000,000 tambah atau tolak 256 kitaran. Ralatnya tidak besar, hanya 0.003%.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 ; Utama ================================================== ======================== Utama: SBIS PIND,6 ; Jika butang ditekan - peralihan RJMP BT_Tolak SETB PORTD,5 ; Jom nyalakan LED2 CLRB PORTD,4 ; Matikan LED1 Seterusnya: LDS R16,TCNT ; Muatkan nombor ke dalam daftar LDS R17,TCNT+1 CPI R16.0x12 ; Mari bandingkan bait demi bait. Bait pertama BRCS NoMatch ; Jika kurang, bermakna ia tidak terkena.

; Utama ================================================== ======================== Utama: SBIS PIND,6 ; Jika butang ditekan - peralihan RJMP BT_Tolak SETB PORTD,5 ; Jom nyalakan LED2 CLRB PORTD,4 ; Matikan LED1 Seterusnya: LDS R16,TCNT ; Muatkan nombor ke dalam daftar LDS R17,TCNT+1 CPI R16.0x12 ; Mari bandingkan bait demi bait. Bait pertama BRCS NoMatch ; Jika kurang, bermakna ia tidak terkena.

CPI R17.0x7A ; Bait kedua BRCS NoMatch ; Jika kurang, bermakna ia tidak terkena. ; Jika ia sepadan, maka kami melakukan tindakan Padanan: INVB PORTD,7,R16,R17 ; LED terbalik3; Sekarang kita perlu menetapkan semula kaunter, jika tidak semasa lelaran yang sama bagi gelung utama; kita akan sampai di sini lebih daripada sekali - pemasa tidak akan mempunyai masa untuk mencapai 255 nilai; supaya nombor dalam dua bait pertama pembilang berubah dan keadaan dicetuskan. ; Sudah tentu, anda boleh memintas ini dengan bendera tambahan, tetapi lebih mudah untuk menetapkan semula kaunter :) CLR R16 ; Kami memerlukan sifar CLI; Akses kepada pembolehubah multibait; serentak dari gangguan dan latar belakang; Akses atom diperlukan. Lumpuhkan gangguan OUTU TCNT0,R16 ; Sifar ke daftar pembilang pemasa STS TCNT, R16 ; Sifar dalam bait pertama pembilang dalam RAM STS TCNT+1,R16 ; Sifar dalam bait kedua pembilang dalam RAM STS TCNT+2,R16 ; Sifar dalam bait ketiga pembilang dalam RAM STS TCNT+3,R16 ; Sifar dalam bait pertama pembilang dalam RAM SEI; Mari dayakan gangguan sekali lagi. ; Jika ia tidak sepadan, kami tidak melakukannya :) NoMatch: NOP INCM CCNT ; Kaunter kitaran berdetik; Walaupun ia tidak digunakan.

JMP Utama BT_Tolak: SETB PORTD,4 ; Nyalakan LED1 CLRB PORTD,5 ; Matikan LED2 RJMP Seterusnya ; Akhir Utama ================================================== ================= ====================

Inilah yang kelihatan seperti dalam tindakan

Dan jika kita perlu mengedipkan diod kedua dengan tempoh yang berbeza, maka kita boleh meletakkan pembolehubah lain dengan selamat ke dalam program, dan dalam pengendali gangguan pemasa kita boleh menambah dua pembolehubah sekaligus. Menyemaknya satu demi satu dalam gelung program utama.

Anda boleh mengoptimumkan proses pengesahan sedikit lagi. Jadikan ia lebih cepat.

Anda hanya perlu membuat akaun bukan naik, tetapi turun. Itu. Kami memuatkan nombor ke dalam pembolehubah dan mula mengurangkannya dalam gangguan. Dan di sana, dalam pengendali, kami menyemaknya untuk sifar. Jika sifar, kemudian tetapkan bendera dalam ingatan. Dan program latar belakang kami menangkap bendera ini dan melancarkan tindakan, pada masa yang sama menetapkan semula kelajuan pengatup.

Tetapi bagaimana jika anda perlu lebih tepat? Nah, hanya ada satu pilihan - untuk menggunakan pemprosesan acara secara langsung dalam pengendali gangguan, dan laraskan nilai dalam TCNT:TCNT0 setiap kali supaya gangguan berlaku tepat pada masa yang betul.

Pelajaran 10 Pemasa-kaunter. menyampuk dalam mikropengawal dan mengapa ia diperlukan, serta apa yang diperlukan menyampuk dan mengapa ia juga diperlukan.

Pemasa-kaunter- ini adalah peranti atau modul dalam mikropengawal yang, seperti namanya, sentiasa mengira sesuatu. Mereka mengira sama ada sehingga nilai tertentu, atau sehingga nilai yang sama dengan kedalaman bit mereka. Mereka sentiasa mengira pada kelajuan yang sama, dengan kelajuan frekuensi jam mikropengawal, diselaraskan untuk pembahagi frekuensi, yang akan kami konfigurasikan dalam daftar tertentu.

Dan pembilang pemasa ini sentiasa dikira jika kita memulakannya.

Pemasa dalam MK Atmega8 tiga.

Dua daripadanya ialah lapan bit pemasa, iaitu pemasa yang boleh mengira sehingga maksimum hanya 255. Nilai ini tidak akan mencukupi untuk kita. Walaupun kita menggunakan pembahagi frekuensi maksimum, bukan sahaja kita tidak akan dapat mengira satu saat, kita tidak akan dapat mengira setengah saat. Dan tugas kami adalah tepat: mengira sehingga 1 saat untuk mengawal peningkatan dalam kiraan penunjuk LED. Anda boleh, tentu saja, juga menggunakan peningkatan pembolehubah kepada nilai tertentu, tetapi saya ingin pengiraan perkakasan sepenuhnya.

Tetapi ada satu lagi pemasa - ini adalah pemasa penuh 16-bit pemasa. Dia bukan sahaja 16-bit, tetapi ia masih mempunyai azimat tertentu yang tidak dimiliki oleh pemasa lain. Kami akan berkenalan dengan pilihan ini kemudian.

Pemasa 16-bit inilah yang akan kita kaji dan gunakan hari ini. Selain itu, setelah membiasakan diri dengan pemasa ini, anda tidak akan memerlukan apa-apa untuk mengkaji operasi dua yang lain secara bebas, kerana ia lebih mudah. Namun begitu, pada masa hadapan kami juga akan mempertimbangkan pemasa 8-bit, kerana satu pemasa tidak akan mencukupi untuk kami mencapai tugas yang lebih kompleks.

Sekarang secara ringkas mengenai gangguan.

menyampuk (Gangguan) adalah mekanisme yang mengganggu kod bergantung pada keadaan tertentu atau persekitaran tertentu yang akan menentukan peranti, modul dan bas tertentu yang terletak dalam mikropengawal.

Terdapat 19 jenis gangguan dalam pengawal Atmega8 kami. Di sini mereka semua dalam jadual dalam dokumentasi teknikal untuk pengawal

Apakah jenis keadaan yang mungkin ada? Dalam kes kami, sebagai contoh, pemasa dikira sehingga nilai tertentu, atau, sebagai contoh, bait dan syarat lain tiba pada sesetengah bas.

Pada masa ini kami akan memproses gangguan, yang terletak dalam jadual yang terletak di atas pada kedudukan 7 - TIMER1 COMPA, dipanggil di alamat 0x006.

Sekarang mari kita lihat pemasa 16-bit kami atau PEMASA1.

Berikut ialah gambarajah bloknya

Kami melihat daftar di sana TCNTn, di mana bilangannya sentiasa berubah, iaitu, ia sentiasa meningkat. Dalam amalan, ini adalah kaunter. Iaitu, daftar ini menyimpan nombor yang telah dikira oleh pemasa.

Dan kepada daftar OCRnA Dan OCRnB(huruf n ialah nombor pemasa, dalam kes kami ia akan menjadi 1) - ini adalah daftar di mana kami memasukkan nombor yang mana nombor dalam daftar TCNTn akan dibandingkan.

Sebagai contoh, kami memasukkan beberapa nombor ke dalam daftar OCRnA dan sebaik sahaja nombor ini bertepatan dengan nilai dalam daftar pengiraan, gangguan akan berlaku dan kami akan dapat memprosesnya. Pemasa dengan gangguan sangat serupa dengan kelewatan biasa dalam kod, hanya apabila kita dalam kelewatan, maka kita tidak boleh melaksanakan sebarang kod pada masa itu (baik, sekali lagi secara kiasan "kita", sebenarnya ALU). Dan apabila pemasa dikira, keseluruhan kod program kami dilaksanakan secara senyap pada masa ini. Jadi kami menang dengan sangat besar, tidak membenarkan sumber besar pengawal terbiar untuk satu saat atau bahkan setengah saat. Pada masa ini kami boleh mengendalikan klik butang, yang juga boleh kami kendalikan dalam pemasa dan banyak lagi.

Terdapat juga daftar TCCR. Daftar ini adalah daftar kawalan. Di sana, bit tertentu dikonfigurasikan yang bertanggungjawab untuk konfigurasi pemasa.

Pemasa juga mempunyai beberapa mod, yang juga akan kita kenali sedikit kemudian.

Ia terdiri daripada dua bahagian, kerana pengawal kami adalah 8-bit dan tidak boleh mempunyai daftar 16-bit. Oleh itu, bahagian tinggi daftar disimpan dalam satu separuh daripada daftar (dan secara fizikal dalam satu daftar), dan bahagian rendah disimpan dalam separuh lagi. Anda juga boleh memanggilnya sebagai pasangan daftar yang terdiri daripada dua daftar berasingan TCCR1A dan TCCR1B. Nombor 1 bermakna daftar milik pemasa 1.

Daftar TCCR ini bertanggungjawab untuk menetapkan pembahagi supaya pemasa tidak dikira begitu cepat, dan ia juga bertanggungjawab (atau lebih tepatnya, bit tertentu) untuk menetapkan mod tertentu.

Bit WGM bertanggungjawab untuk menetapkan mod

Kami melihat banyak mod yang berbeza di sini.

Biasalah- ini adalah mod biasa, pemasa dikira sehingga tamat.

PWM- Ini PWM hanya varieti yang berbeza, iaitu pemasa boleh memainkan peranan modulator lebar nadi. Kita akan berkenalan dengan teknologi ini dalam pelajaran kemudian.

CTC- ini adalah penetapan semula secara kebetulan, hanya apa yang kita perlukan. Di sinilah daftar TCNT dan OCR dibandingkan. Terdapat dua mod sedemikian, kita memerlukan yang pertama, yang kedua berfungsi dengan daftar yang berbeza.

Kami tidak akan mengkaji semua jenis mod dalam pelajaran ini. Apabila kami memerlukan mod ini, maka kami akan memikirkannya.

Baiklah, jangan menyiksa diri kita dengan dokumentasi dan akhirnya cuba memasukkan sesuatu ke dalam beberapa daftar.

Kod itu, seperti biasa, dicipta daripada projek sebelumnya. Untuk Proteus, kod itu juga telah disalin dan dinamakan semula daripada pelajaran lepas, dan laluan ke perisian tegar baharu telah ditunjukkan dalam sifat pengawal. Kami akan menamakan projek Ujian07.

Mari cuba, seperti biasa, untuk menyusun kod dan menjalankannya dalam Proteus. Jika semuanya berfungsi dengan baik, maka kami mula menambah kod baharu.

Mari tambah satu lagi fungsi, kerana kita belajar cara menambah fungsi dalam pelajaran lepas. Kod fungsi akan diletakkan selepas fungsi segchar dan sebelum fungsi utama. Selepas itu, disebabkan fakta bahawa kami akan memanggil fungsi segchar di dalam fungsi baharu kami.

Selain itu, kami akan membuat bukan satu fungsi, tetapi dua. Kami akan meletakkan semua kod permulaan untuk pemasa kami dalam satu fungsi, dan fungsi lain akan menjadi pengendali gangguan pemasa, dan fungsi tersebut adalah khusus dan tidak perlu dipanggil. Apabila keperluan timbul, mereka akan memanggil diri mereka bergantung pada syarat-syarat tertentu yang dinyatakan di atas.

Oleh itu, kami akan memanggil fungsi pertama pemasa_ini

//———————————————

batalpemasa_ini( batal)

{

}

//———————————————

Juga, mari kita pisahkan fungsi kita, serta beberapa blok lengkap dengan pengisytiharan pembolehubah global, dengan prototaip fungsi, antara satu sama lain dengan baris ini, yang, disebabkan kehadiran dua garis miring di hadapan, pengkompil tidak akan memproses dan akan ambil mereka sebagai komen. Disebabkan persempadanan ini, kita akan melihat di mana satu fungsi berakhir dan satu lagi bermula.

Fungsi ini, seperti yang kita lihat, tidak mempunyai sebarang hujah - tidak ada input atau pulangan. Mari segera panggil fungsi ini dalam fungsi main().

tidak ditandatanganicharbutcount=0,butstate=0;

pemasa_ini();

Sekarang kita akan mula perlahan-lahan mengisi fungsi ini dengan kod.

Mari kita mulakan dengan daftar kawalan pemasa, contohnya TCCR1B. Menggunakan operasi "ATAU" kegemaran kami, kami akan memasukkan satu ke dalam bit tertentu dalam daftar

batalpemasa_ini( batal)

TCCR1B|= (1<< WGM12);

Daripada ulasan kami melihat bahawa kami sedang bekerja dengan bit mod, dan kami akan menetapkan hanya bit WGM12 daripadanya, meninggalkan yang lain sebagai sifar. Berdasarkan ini, kami mengkonfigurasi mod ini:

Pemasa juga mempunyai daftar berikut: TIMSK. Daftar ini bertanggungjawab untuk topeng gangguan - Topeng Sampuk. Daftar ini tersedia untuk semua pemasa, bukan sahaja untuk yang pertama, ia adalah perkara biasa. Dalam daftar ini kita akan menetapkan bit OCIE1A, yang akan membolehkan jenis gangguan yang kami perlukan TIMER1 COMPA

TCCR1B|= (1<< WGM12); // tetapkan mod CTC (set semula secara kebetulan)

TIMSK|= (1<< OCIE1A);

Sekarang mari kita bermain dengan daftar perbandingan itu sendiri OCR1A(H dan L). Untuk melakukan ini, anda perlu melakukan sedikit matematik. Daftar OCR1AH menyimpan bahagian utama nombor untuk perbandingan, dan daftar OCR1AL- yang bongsu.

Tetapi sebelum kita mengira, mari kita menulis kod dengan mana-mana nilai daftar ini dan kemudian membetulkannya, kerana kita kemudiannya akan memulakan pembahagi dan ia juga akan mengambil bahagian dalam mengira masa pengiraan yang diperlukan. Tanpa pembahagi, pemasa akan mengira terlalu cepat.

TIMSK|= (1<< OCIE1A); // tetapkan bit daya sampuk pembilang pertama bertepatan dengan OCR1A(H dan L)

OCR1AH= 0b10000000;

OCR1AL= 0b00000000;

TCCR1B|= ( ); //tetapkan pembahagi.

Kami belum memasang sebarang pembahagi lagi, kerana kami belum mengiranya lagi. Jom buat ini.

Pada masa ini dalam daftar kami OCR1A nombor 0b1000000000000000 ditemui, yang sepadan dengan nombor perpuluhan 32768.

Pengawal mikro kami beroperasi, seperti yang kami bersetuju, pada frekuensi 8,000,000 Hz.

Bahagikan 8,000,000 dengan 32,768 untuk mendapatkan lebih kurang 244.14. Ini ialah kekerapan dalam hertz yang pemasa kita akan beroperasi jika kita tidak menggunakan pembahagi. Iaitu, nombor kami akan berubah 244 kali sesaat, jadi kami tidak akan melihatnya. Oleh itu, anda perlu menggunakan pembahagi kekerapan pemasa. Mari kita pilih pembahagi sebanyak 256. Ia sesuai untuk kita, dan kemudian kita akan membetulkannya tepat sehingga 1 Hz menggunakan nombor perbandingan.

Berikut ialah pembahagi untuk 1 pemasa:

Saya telah menyerlahkan pembahagi yang kita perlukan dalam jadual. Kami melihat bahawa kami hanya perlu menetapkan bit CS12.

Oleh kerana pembahagi frekuensi kami ialah 256, kami membahagikan 8000000 dengan pembahagi ini, kami mendapat 31250, dan ini adalah nombor yang mesti kami masukkan dalam TCNT. Pemasa kami akan mengira sehingga nombor ini untuk mengira hingga 1 saat. Nombor 31250 ialah 0b0111101000010010 dalam perwakilan binari. Mari letakkan nombor ini dalam pasangan daftar, dan juga gunakan pembahagi

OCR1AH= 0b 01111010 ; //tulis nombor pada daftar untuk perbandingan

OCR1AL= 0b 00010010 ;

TCCR1B|= (1<< CS12 ); //tetapkan pembahagi.

Itu sahaja dengan fungsi ini.

Kini fungsi seterusnya ialah pengendali gangguan pemasa kebetulan. Ia ditulis seperti ini

ISR( TIMER1_COMPA_vect)

{

}

Dan badan fungsi ini akan dilaksanakan sendiri apabila berlakunya nombor yang kebetulan.

Kami memerlukan pembolehubah. Mari kita mengisytiharkannya secara global, pada permulaan fail

#termasuk

//———————————————

tidak ditandatanganichari;

//———————————————

Sehubungan itu, kami akan mengalih keluar pembolehubah yang sama daripada kod dalam fungsi main().

intutama( batal)

tidak ditandatanganichari;

Mari kita juga mengulas semua kod dalam gelung tak terhingga. Peranannya kini akan dimainkan oleh pemasa, dan saya fikir ia akan menangani perkara ini juga, dan lebih baik lagi, tanpa mengganggu "sesiapa sahaja".

sementara(1)

{

// untuk(i=0;i<10;i++)

// {

// while (butstate ==0)

// {

// jika (!(PINB&0b00000001))

// {

// jika(butcount< 5)

// {

//butcount++;

// }

//lain

// {

// i=0;

//butstate=1;

// }

// }

//lain

// {

// if(butcount > 0)

// {

//butcount—;

// }

//lain

// {

//butstate=1;

// }

// }

// }

// segchar(i);

// _delay_ms(500);

//butstate=0;

// }

Sekarang, sebenarnya, badan fungsi pengendali. Di sini kita akan memanggil fungsi segchar. Kemudian kita akan meningkat sebanyak 1 pembolehubah i. Dan supaya ia tidak melebihi nombor satu digit, kami akan menetapkan semulanya kepada sifar di bawah syarat ini

ISR( TIMER1_COMPA_vect)

jika( i>9) i=0;

segchar( i);

i++;

Sekarang mari kita betulkan sedikit kod pada permulaan fungsi main(). Pelabuhan D, yang bertanggungjawab untuk keadaan segmen, kami akan menetapkannya kepada segmen supaya apabila kami menghidupkannya, penunjuk tidak menyala, kerana ia mempunyai anod biasa. Kemudian kita akan meletakkan nombor 0 ke dalam pembolehubah global i di sini, hanya untuk pesanan. Secara umum, sebagai peraturan, pada permulaan, pembolehubah yang tidak dimulakan sentiasa sifar. Tetapi kami masih akan memulakannya. Dan, yang paling penting, agar gangguan pemasa berfungsi, ia tidak mencukupi untuk memasukkannya ke dalam permulaan pemasa. Selain itu, secara amnya, agar semua gangguan berfungsi, gangguan global mesti didayakan. Terdapat fungsi khas untuk ini sei() — Set Interrupt.

Sekarang kod akan menjadi seperti ini

DDRB= 0x00;

PORTD= 0b 11111111 ;

PORTB= 0b00000001;

i=0;

sei();

sementara(1)

Kami juga perlu memasukkan fail perpustakaan sampukan pada permulaan fail

#termasuk

#termasuk

#termasuk

Selain itu, kami tidak memerlukan pembolehubah untuk butang itu lagi, kerana kami tidak akan berfungsi dengan butang itu hari ini. Mari komen mereka

intutama( batal)

//unsigned char butcount=0, butstate=0;

pemasa_ini();

Mari kumpulkan kod kami dan semak prestasinya terlebih dahulu dalam Proteus. Jika semuanya berfungsi dengan baik, maka kami juga akan menyemaknya dalam litar langsung

Semuanya berfungsi untuk kita. Hebat!

Beginilah rupa jam randik itu. Tetapi kerana kami tidak mempunyai resonator kuarza, jam randik ini tidak boleh dipanggil tepat.

Namun begitu, hari ini kami banyak belajar. Kami belajar tentang gangguan, kami juga belajar cara memprosesnya, kami belajar cara bekerja dengan pemasa, mengkonfigurasi beberapa daftar mikropengawal baharu, sebelum itu kami hanya bekerja dengan daftar port. Selain itu, disebabkan semua ini, kami telah melegakan peranti logik aritmetik mikropengawal kami dengan ketara.

Tonton VIDEO TUTORIAL

Paparan Siaran: 17,258