Koneksi Atmega8. Sensor jarak URM37 - koneksi ke AVR dan komputer (melalui USB)

Artikel ini akan membahas cara menghubungkan LED ke mikrokontroler, bekerja dengan port dan menulis program dalam SI. Artikel ini terutama ditujukan bagi pemula yang baru mempelajari mikrokontroler AVR.

Pertama, Anda perlu memilih mikrokontroler. Dalam kasus saya ini adalah ATmega8535. Dalam hal ini, Anda dapat menggunakan mikrokontroler apa pun, karena tugas ini dapat dengan mudah diimplementasikan di bawah mikrokontroler apa pun. Anda dapat menulis program untuk mikrokontroler di Majelis, SI, Pascal dan Bascom. Saya menggunakan bahasa SI, semua bahasa ini berbeda.
Perbedaan spesifik antara C dan Pascal dapat dilihat di bawah ini.

//LED berkedip void main() ( ddrB = 0b11111111; //mengatur port B ke output portB = 0b11111111; //secara default semuanya mati while(1) ( portB = ˜portB; //mengalihkan status LED ke sebaliknya delay_ms(100 ); //penundaan sebesar 100 milidetik ) )

Program Pertama; mulai ddrB:= $FF; //atur port B ke port keluaranB:= $FF; //tidak ada yang menyala secara default sementara(1) mulai portB:= tidak(portB); //mengalihkan status LED ke penundaan terbalik_ms(100); //mengakhiri penundaan sebentar; akhir.

Daftar elemen radio

Penamaan Jenis Denominasi Kuantitas CatatanTokobuku catatan saya
U1 MK AVR 8-bit

ATmega8535

1 Ke buku catatan
R1-R8 Penghambat

220 Ohm - 1 kOhm

8 Ke buku catatan
R9-R11 Penghambat

10 kOhm

3 Ke buku catatan
V1-V8 Dioda pemancar cahaya 8 Ke buku catatan
Tombol kebijaksanaan 3

Kami meniru sirkuit dalam program Proteus, mengedipkan LED, dan mempelajari cara mem-flash mikrokontroler virtual kami. Pasti banyak dari pembaca yang berpikir: “Apakah mungkin untuk mengedipkan LED menggunakan tombol yang terhubung ke MK?

Ya, tentu saja mungkin. Cukup mudah untuk diterapkan. Selain itu, Anda dapat meniru tombol dengan atau tanpa fiksasi. Selain itu, dalam program Proteus, Anda dapat menggunakan kedua jenis tombol menggunakan makro tombol yang sama. Dalam kasus apa hal ini mungkin berguna? Misalnya, kita perlu memilih mode pengoperasian perangkat. Mari kita lihat lebih dekat bagaimana mengimplementasikannya menggunakan mikrokontroler dan melakukan emulasi pada program Proteus.


Untuk mendapatkan gambaran yang jelas bahwa kita benar-benar memiliki dua pilihan mode, kita akan merakit rangkaian sederhana dengan 4 LED dengan kontrol satu tombol. Pada opsi pertama, LED pertama hingga keempat menyala secara bergantian. Dengan pilihan kedua, hal yang sama, tetapi dalam urutan terbalik, yaitu dari yang keempat ke yang pertama. Satu-satunya hal yang ingin saya klarifikasi adalah bahwa tombol kami disurvei untuk ditekan atau dilepaskan hanya sebelum efeknya dimulai. Hingga efeknya selesai bekerja, program tidak merespons dengan menekan atau melepaskan tombol.

Jadi langsung pada intinya. Seperti inilah tampilan diagram kita di program Proteus (klik untuk memperbesar):

Pada skema ini kita sudah melihat perbedaan dari skema yang kami kumpulkan di artikel sebelumnya. Di sisi kiri diagram kita melihat sebutan tombol dan sumber listrik +5 volt.

Seperti yang telah kita bahas, kita mengambil alih kekuasaan dan mendarat di tab “Terminal”. Kami menetapkannya masing-masing sebagai Kekuatan dan Tanah.

Kami menyatakan catu daya rangkaian dengan segitiga dengan garis yang membagi tingginya. Di dekatnya, pada gambar, adalah penunjukan tombol. Di sebelah kanan tombol kita melihat lingkaran merah berisi panah berkepala dua. Jika Anda mengkliknya selama emulasi, tombol tersebut akan diperbaiki dan akan terus ditekan. Setelah menekannya lagi, fiksasinya dilepas.


Sebelum digunakan, kita perlu memilih tombol di perpustakaan dengan cara yang sama seperti bagian lainnya. Untuk melakukan ini, ketikkan kata “tetapi” di kolom “Mask”. Kemudian pada kolom “Hasil” ada kata “TOMBOL”:


Setelah ini, tombol tersebut akan muncul di daftar kami, bersama dengan bagian-bagian terpilih yang digunakan dalam proyek.

Port apa yang kami gunakan dalam proyek ini? Gambar di bawah ini kita melihat jalur keluar dari port PA0, PB0, PB1, PB2 dan PB3. Kami memiliki LED yang terhubung ke port B, dan tombol ke port A.

Jadi, ketika ditekan, kita menutup rangkaian yang menghubungkan +5 volt ke port PA0 dan terminal atas resistor. Mengapa kita memasang resistor di sini? Faktanya rangkaian tombol harus ditutup. Setelah kita memasang resistor, arus mengalir dari catu daya positif melalui tombol, resistor dan selanjutnya ke ground.

Cukup dengan mengambil nilai resistor sebesar 200 Ohm. Jadi, ketika kita menekan tombol tersebut, kita menghubungkan port PA0 ke daya +5 volt, dan jika kita melakukan polling pada pin PA0 untuk mengetahui ada tidaknya tegangan, kita dapat mempengaruhi eksekusi program kita.

Saya telah memberikan tangkapan layar dengan teks program kami di bawah ini:


Jadi perbedaannya dengan proyek sebelumnya adalah kita mengkonfigurasi semua 8 pin port RA sebagai input, kita mengkonfigurasi pin port PB0 - PB3 sebagai output, dan PB4 - PB7 sebagai input.


Kemudian kami menggunakan uji kondisi dalam program kami “ jika"


Jadi, kita melihat di baris setelah “if”, dalam tanda kurung, kondisi eksekusi. Kode di bawah ini dijalankan jika kita memiliki logika nol, atau nol volt, pada port PA0. Teks dalam tanda kurung ini adalah pergeseran bit port. Kami akan menganalisisnya di salah satu artikel berikut, tetapi untuk saat ini cukup yakin bahwa dengan melakukan ini kami melakukan polling pada tombol push-up. Kemudian di dalam kurung kurawal muncul teks program yang dijalankan jika kondisinya benar. Jika kondisinya tidak benar, program akan melanjutkan eksekusi, melewatkan teks dalam kurung kurawal.

Demikian pula, dengan menggunakan kondisi “jika”, kita melakukan polling pada tombol aktif mendesak. Harap dicatat bahwa teks dalam tanda kurung telah berubah. Artinya jika kita mempunyai satuan logika pada kaki PA0, maka kita memenuhi syarat yaitu teks dalam tanda kurung kurawal. Artinya, ketika tombol ditekan, LED pertama hingga keempat menyala dan padam satu per satu, dan ketika ditekan dan ditahan, LED keempat hingga pertama menyala dan padam. Dengan demikian, kita dapat mempengaruhi eksekusi program dengan menekan sebuah tombol, melakukan polling untuk mengetahui keberadaan logika nol atau logika di dalamnya.

Juga, yang berisi file “Sishnik”, HEX dan file Proteus.

Dan inilah videonya

Metode jam

Cara kanonik untuk mencatat waktu MK adalah dengan menghubungkan resonator kuarsa ke pin yang sesuai (Gbr. 18.11, a). Kapasitansi kapasitor C1 dan C2 pada umumnya harus 22-36 pF (untuk penyertaan kuarsa, lihat Bab 15). Kebanyakan model Tiny dan Mega memiliki bit konfigurasi khusus yang memungkinkan Anda mengatur konsumsi. Ketika bit ini disetel ke satu (tidak terprogram), amplitudo osilasi berkurang, namun rentang frekuensi yang mungkin dan kekebalan kebisingan secara keseluruhan menyempit, jadi tidak disarankan menggunakan mode ini (lihat di bawah). Resonator kuarsa frekuensi rendah juga dapat digunakan (misalnya, "jam" 32.768 Hz), sedangkan kapasitor C1 dan C2 tidak perlu dipasang, karena ketika kemiringan diatur ke nilai O, kapasitor internal 36 pF disertakan di MC terhubung.

Resonator keramik dapat digunakan sebagai pengganti kuarsa. Penulis baris ini mampu menjalankan MK pada frekuensi non-standar, menggunakan induktansi mini sebagai pengganti kuarsa dalam sambungan yang sama (dengan nilai 4,7 H dan kapasitas kapasitor 91 pF, frekuensinya sekitar 10 MHz).

Beras. 18.11. Metode pencatatan jam kerja mikrokontroler AVR menggunakan: a - resonator kuarsa; b - generator eksternal; c - rantai RC

Secara alami, MK juga dapat di-clock dari generator eksternal (Gbr. 18.11, b). Hal ini sangat berguna ketika Anda perlu menyinkronkan MK dengan komponen eksternal, atau memiliki frekuensi clock yang sangat tepat saat menggunakan generator yang sesuai (misalnya, seri SG-8002 dari Epson).

Sebaliknya, bila akurasi tidak diperlukan, Anda dapat menggunakan rantai LAN eksternal (Gbr. 18.11, c). Di sirkuit ini, kapasitansi C1 harus minimal 22 pF, dan resistor R1 dipilih dari kisaran 3,3-100 ohm. Dalam hal ini, frekuensi ditentukan dengan rumus F = 2/3 RC, CI tidak dapat diatur sama sekali jika Anda menulis nol logis di sel konfigurasi SCR, sehingga menghubungkan kapasitor internal 36 pF.

Terakhir, Anda dapat melakukannya tanpa komponen eksternal sama sekali - gunakan generator IG internal, yang dapat beroperasi pada empat frekuensi, kira-kira sama dengan 1, 2, 4, dan 8 MHz. Fitur ini paling baik digunakan pada mod kelas bawah (1x Tiny, tersedia dalam paket 8-pin - kemudian pin yang dimaksudkan untuk menghubungkan resonator atau osilator eksternal dapat digunakan untuk tujuan lain, seperti port I/O biasa. Keluarga klasik dari osilator RC bawaan tidak memilikinya.

Secara default, MK dari keluarga Tiny dan Mega diatur untuk bekerja dengan osilator internal pada frekuensi 1 MHz (cksel = oooi), jadi untuk beroperasi dalam mode lain, Anda perlu mengatur sel konfigurasi cksel yang sesuai (lihat Tabel 18.1). Cara melakukan hal ini dalam praktiknya akan dibahas pada Bab 19. Nilai yang disarankan dari sel-sel ini untuk resonator konvensional dari 1 MHz dan lebih banyak lagi yang ada di sel cksel, dan nol di sk.

Detail

Saat memasang sel, harus diperhitungkan bahwa keadaan cksel = oooo (cermin sehubungan dengan nilai yang paling umum digunakan untuk resonator kuarsa iiii) menempatkan MK ke mode jam dari osilator eksternal, dan dalam keadaan ini bahkan tidak bisa diprogram tanpa menerapkan frekuensi eksternal. Selain itu, jika Anda mencoba mengatur mode dengan resonator frekuensi rendah, MC frekuensi tinggi tidak akan mulai lagi, dan tidak semua pemrogram dapat bekerja pada frekuensi clock rendah seperti itu. Oleh karena itu, ketika memanipulasi sel, dan bukan hanya cksel, Anda harus sangat berhati-hati dan memiliki gagasan yang baik tentang apa sebenarnya yang Anda instal. Hal ini dibahas lebih rinci pada bab berikutnya.

Tabel 18.1. Mengatur sel konfigurasi CKSEL tergantung pada mode jam

Sumber jam

Frekuensi eksternal

Generator /?C bawaan

Osilator RC bawaan

Generator /?C bawaan

Osilator RC bawaan

Rantai RC eksternal

Eksternal /?C-rantai

Rantai RC eksternal

Rantai RC eksternal

Resonator frekuensi rendah

Tabel 16.1 (akhir)

Sumber jam

Resonator keramik

Resonator keramik

resonator kuarsa

Resonator kuarsa

Port I/O paralel

Port I/O (kami ulangi agar tidak tertukar dengan register I/O atau port serial MK untuk bertukar informasi dengan perangkat eksternal) dalam model yang berbeda dapat berkisar dari 1 hingga 7. Port-port tersebut secara nominal 8-bit, dalam beberapa kasus Kapasitas bit dibatasi oleh jumlah pin paket dan bisa kurang dari delapan. Port ditandai dengan huruf A, B, C, D, dll., dan tidak harus berurutan: pada model yang lebih rendah mungkin hanya ada, misalnya, port B dan D (seperti pada ATtiny2313) atau umumnya hanya satu port B (seperti pada ATtinylx).

Untuk mengurangi jumlah kontak dalam casing, pada sebagian besar kasus, pin eksternal yang sesuai dengan port, selain fungsi utamanya (input/output dua arah), juga memiliki pin tambahan. Perhatikan bahwa kecuali untuk pin Reset, jika dapat beroperasi dalam mode alternatif, tidak diperlukan peralihan pin port khusus. Jika, misalnya, Anda menginisialisasi port serial UART dalam program Anda, maka pin port yang sesuai (misalnya, di ATmega8335 ini adalah pin port PDO dan PD1) akan berfungsi dalam fungsi alternatif, sebagai input dan output UART. Namun, dalam interval antara penggunaan pin khusus tersebut, pada prinsipnya pin tersebut dapat digunakan sebagai pin dua arah biasa. Dalam praktiknya, perlu menggunakan langkah-langkah desain sirkuit untuk mengisolasi fungsi satu sama lain, sehingga tidak disarankan untuk menyalahgunakan fitur ini.

Pin port cukup otonom, dan modenya dapat diatur secara independen satu sama lain. Secara default, ketika daya dihidupkan, semua perangkat tambahan dinonaktifkan, dan port berfungsi sebagai input, dan berada dalam kondisi ketiga dengan kecepatan tinggi (yaitu, dengan impedansi input tinggi). Bekerja untuk keluaran memerlukan instruksi khusus, yang mana dalam program ini Anda perlu mengatur bit yang sesuai dengan keluaran yang diinginkan dalam register arah data (register ini disebut DDRx, di mana x adalah huruf yang menunjukkan port tertentu, misalnya untuk port A itu akan menjadi ddra). Jika bit direset (yaitu, sama dengan logika nol), maka output berfungsi sebagai input (seperti secara default); jika disetel (yaitu, sama dengan logika), maka bit tersebut berfungsi sebagai output.

Untuk mengatur output ke satu keadaan, Anda perlu mengatur bit yang sesuai secara terpisah dalam register data port (dilambangkan dengan portx), dan untuk mengaturnya ke O, setel ulang bit ini. Arah pengoperasian keluaran (input-output, register DDRx) dan statusnya (O-1, portx) tidak boleh tertukar.

Register data portx sebenarnya hanyalah buffer keluaran, apa pun yang ditulis ke dalamnya akan segera dikeluarkan. Tetapi jika Anda menyetel pin port ke input (yaitu, menulis nol logis ke register arah ddrx), seperti yang dilakukan secara default, maka register data portx akan memainkan peran yang sedikit berbeda - menyetel bitnya ke nol berarti bahwa input berada pada keadaan ketiga dengan resistansi tinggi, dan menyetelnya ke satu akan menghubungkan resistor “pull-up” dengan resistansi 35-120 kOhm ke terminal.

Catatan di pinggir

Dalam kebanyakan kasus, resistor pull-up bawaan tidak cukup untuk pengoperasian yang andal - karena interferensi, MC mungkin tidak berfungsi, dan lebih baik memasang resistor eksternal tambahan secara paralel dengan resistor internal ini, dengan resistansi 1 hingga 5 kOhm (dalam kasus konsumsi yang kritis, nilainya dapat ditingkatkan menjadi 20-30 kOhm). Misalnya, jika Anda menghubungkan tombol eksternal dengan dua pin ke input, yang dialihkan ke ground, atau pin tersebut bekerja pada "bus umum" dengan perangkat jarak jauh (terletak di papan lain), atau pin tersebut menjalankan fungsi sebuah interupsi eksternal (lihat di bawah), maka resistor tambahan tersebut harus dihubungkan.

Prosedur membaca level pada pin port jika dalam keadaan input tidak sepenuhnya sepele. Sangat menggoda untuk membaca data dari register data portx, tetapi ini tidak akan menghasilkan apa-apa - Anda hanya akan membaca apa yang Anda tulis sebelumnya di sana. Dan untuk membaca apa yang sebenarnya tersedia pada input (langsung pada output dari rangkaian mikro), disediakan kemungkinan lain. Untuk melakukan ini, Anda perlu mengakses beberapa array, yang dilambangkan dengan pinx. Akses dilakukan dengan cara yang sama seperti bit individual RVV konvensional (lihat Bab 19\ tetapi pinx bukanlah sebuah register, ia hanyalah rentang alamat tertentu, yang pembacaannya menyediakan akses ke informasi dari elemen buffer pada input port. Menulis sesuatu ke alamat piNx, tentu saja, tidak mungkin.

Interupsi

Seperti pada PC, interupsi pada mikrokontroler hadir dalam dua jenis. Namun jika dalam PC interupsi dibagi menjadi hardware (misalnya dari timer atau keyboard) dan software (sebenarnya bukan interupsi, melainkan subrutin yang tertulis di BIOS - dengan menyebarnya Windows, konsep ini hampir hilang dari praktik programmer), kemudian di MK, tentu saja, semua Interupsi adalah perangkat keras, dan dibagi menjadi internal dan eksternal. Setiap gangguan secara terpisah, serta kemungkinan terjadinya secara umum, memerlukan izin khusus sebelumnya.

Harus dipahami dengan tegas bahwa untuk menginisialisasi interupsi apa pun, Anda perlu melakukan empat hal dalam program: mengaktifkan interupsi secara umum (dinonaktifkan secara default), kemudian mengaktifkan interupsi khusus ini, mengatur salah satu mode yang tersedia untuk itu dan, akhirnya , atur vektor interupsi: penunjuk ke label , di mana prosedur subrutin pengendali interupsi berada. Dan, tentu saja, setelah ini Anda perlu menulis handlernya sendiri, jika tidak semua ini akan sia-sia. Hal ini dibahas lebih rinci di Bab 19.

Interupsi internal dapat timbul dari perangkat apa pun yang merupakan tambahan pada inti sistem - dari pengatur waktu, dari komparator analog, dari port serial, dll. Interupsi internal adalah peristiwa yang terjadi pada sistem dan mengganggu pelaksanaan program utama. Sistem interupsi internal di AVR cukup luas dan mewakili sistem utama untuk interaksi perangkat dengan inti sistem, dan kami akan kembali ke masalah ini lebih dari sekali.

AVR MK memiliki setidaknya dua interupsi eksternal, INTO, INT1 (kebanyakan Mega memiliki interupsi ketiga - ICHT2). Interupsi eksternal adalah peristiwa yang terjadi ketika sinyal muncul pada salah satu input yang dirancang khusus untuk tujuan ini. Ada tiga jenis kejadian yang menyebabkan interupsi, dan kejadian tersebut dapat diatur dalam perangkat lunak: ini bisa berupa level tegangan rendah, atau tepi positif atau negatif pada pin yang sesuai. Menariknya, interupsi untuk semua kejadian ini dijalankan bahkan jika pin port yang sesuai dikonfigurasi sebagai output.

Mari kita lihat secara singkat fitur penggunaan mode ini. Interupsi tingkat rendah (mode diatur secara default, untuk menginisialisasinya, cukup aktifkan interupsi yang sesuai) terjadi setiap kali input yang sesuai rendah. “Setiap waktu” berarti benar-benar setiap waktu, yaitu jika impuls negatif berlangsung selama beberapa waktu, maka prosedur pemrosesan interupsi, setelah berakhir, akan diulangi lagi dan lagi, sehingga program utama tidak dapat bekerja. Oleh karena itu, skema umum untuk menggunakan mode interupsi eksternal ini adalah dengan segera menonaktifkannya saat terjadi (prosedur pemrosesan, setelah dimulai, akan diselesaikan satu kali) dan mengaktifkannya kembali hanya ketika pengaruh eksternal seharusnya sudah berakhir (misalnya, jika itu adalah tombol yang ditekan, maka itu harus diizinkan lagi oleh pengatur waktu setelah satu atau dua detik).

Sebaliknya, interupsi naik atau turun dieksekusi satu kali. Tentu saja tidak ada perlindungan terhadap pantulan kontak dan tidak mungkin ada, karena MK tidak mampu membedakan pantulan dari rangkaian pulsa pendek. Jika ini penting, Anda perlu mengambil tindakan eksternal untuk melindungi dari pantulan, atau menggunakan metode yang sama seperti untuk interupsi level - di dalam prosedur pengendali interupsi, nonaktifkan interupsi itu sendiri dengan perintah pertama, dan setelah beberapa waktu di prosedur lain ( berdasarkan pengatur waktu atau peristiwa lain) untuk menyelesaikannya kembali (metode “anti-pentalan” ini sebenarnya identik dengan penggunaan perangkat sekali tembak, lihat Bab 15).

Detail

Pembaca yang penuh perhatian memiliki pertanyaan yang sah - mengapa kita memerlukan mode interupsi tingkat eksternal? Faktanya adalah bahwa di semua model ini dilakukan secara asinkron - pada saat level rendah muncul pada output MK. Tentu saja, deteksi interupsi hanya dapat terjadi pada akhir instruksi saat ini, sehingga pulsa yang sangat pendek mungkin hilang. Tetapi interupsi INTO dan INT1 dalam mode kontrol tepi untuk sebagian besar model ditentukan sebaliknya, hanya secara sinkron - pada saat perbedaan level sinyal jam pengontrol, sehingga durasinya tidak boleh lebih pendek dari satu periode jam . Tapi ini bukan hal yang paling penting: pada umumnya, tidak akan ada perbedaan dalam mode ini jika bukan karena mode sinkron tentu memerlukan kehadiran sinyal clock ini. Oleh karena itu, interupsi eksternal asinkron, oleh karena itu, dapat "membangunkan" pengontrol yang berada dalam salah satu mode hemat daya yang dalam, ketika generator jam tidak berfungsi, tetapi generator jam tidak berfungsi. Dan MCU biasa, seperti AT90S8515 dari keluarga Classic (tetapi bukan mega-analognya!), hanya dapat dibangunkan dari “tidur” nyenyak melalui interupsi tingkat eksternal, yang tidak selalu nyaman untuk digunakan. Sebagian besar model keluarga Meda (dari model yang lebih muda - kecuali ATmegaS) memiliki interupsi lain, INT2, yang hanya terjadi pada edge (tidak bisa berdasarkan level), tetapi, tidak seperti INTO dan INT1, secara asinkron. Dalam ATtiny2313 (tetapi tidak dalam analog "klasik"!) Interupsi asinkron seperti itu dapat terjadi melalui sinyal dari salah satu dari 8 pin port B. Hal ini secara signifikan meningkatkan kegunaan pengontrol dalam mode hemat daya.

Penghitung waktu-penghitung

Kebanyakan AVR MK memiliki dua atau tiga penghitung waktu, salah satunya 16-bit, dan sisanya 8-bit (dalam model Mega lama, jumlah penghitung bisa mencapai 6). Semua penghitung memiliki kemampuan untuk memuat nilai sebelumnya dan dapat beroperasi langsung dari frekuensi jam prosesor (SC) atau dari frekuensi tersebut, dibagi dengan 8, 64, 256 atau 1024 (dalam beberapa kasus dengan 16 dan 32), serta dari sebuah sinyal eksternal. Secara umum, desain pengatur waktu di MK, seperti yang kami katakan, mirip dengan penghitung 561HEU/14 (lihat Bab 15), hanya saja fungsinya diperluas secara signifikan.

Dalam arsitektur AVR, counter-timer 8-bit diberi nomor O dan 2, dan counter-timer 16-bit diberi nomor 1, 3, dan seterusnya. Beberapa penghitung 8-bit (biasanya Timer 2, jika ada dua di antaranya) dapat beroperasi dalam mode asinkron dari generator jam yang terpisah, dan terus berfungsi bahkan jika MCU lainnya berada dalam keadaan "tidur", yang memungkinkannya untuk digunakan sebagai jam waktu nyata.

Saat menggunakan penghitung waktu sebagai penghitung pulsa eksternal biasa (dan reaksi dimungkinkan baik pada saat jatuh maupun di tepi pulsa), frekuensi pulsa yang dihitung tidak boleh melebihi setengah frekuensi generator jam MK (dan dengan berliku-liku eksternal asimetris, instruksi merekomendasikan nilai frekuensi pembatas yang lebih rendah lagi - 0,4 dari jam). Hal ini disebabkan oleh fakta bahwa ketika menghitung pulsa eksternal, tepinya terdeteksi secara serempak (pada momen tepi positif dari sinyal clock). Selain itu, perlu diperhatikan bahwa penundaan dalam memperbarui isi penghitung setelah kedatangan pulsa eksternal bisa mencapai 2,5 periode jam.

Ini adalah batasan yang cukup kuat, oleh karena itu, misalnya, menggunakan MK sebagai pengukur frekuensi universal sangat tidak nyaman - lebih baik merancang sirkuit berkecepatan tinggi menggunakan logika kombinasional atau FPGA (rangkaian terintegrasi logika yang dapat diprogram) yang sesuai.

Ketika counter overflow terjadi, suatu peristiwa terjadi yang dapat memicu interupsi terkait. Penghitung Timer O 8-bit terbatas pada fungsi ini dalam beberapa kasus. Timer 2, jika ada, juga dapat memicu interupsi jika nilai yang dihitung sesuai dengan nilai yang telah ditentukan. Pencacah 16-bit lebih “canggih” dan dapat menyebabkan interupsi ketika keduanya bertepatan dengan dua angka A dan B yang ditentukan secara independen. Dalam hal ini, pencacah dapat diatur ulang ke nol atau melanjutkan penghitungan, dan pulsa dapat dihasilkan pada pin khusus (dalam perangkat keras, tanpa partisipasi program).

Selain itu, pencacah 16-bit dapat “menangkap” pulsa tunggal eksternal pada pin khusus. Dalam hal ini, interupsi dapat dipanggil, dan isi counter ditempatkan dalam register tertentu. Penghitung itu sendiri dapat diatur ulang ke nol dan mulai menghitung lagi, atau terus menghitung. Mode ini nyaman digunakan untuk mengukur periode sinyal eksternal atau untuk menghitung kejadian tidak teratur tertentu (seperti lewatnya partikel dalam pencacah Geiger). Penting bahwa sumber kejadian tersebut juga dapat berupa pembanding analog bawaan, yang kemudian digunakan sebagai pembentuk pulsa.

Semua penghitung waktu dapat beroperasi dalam apa yang disebut. Mode PWM, yaitu sebagai modulator lebar pulsa (PWM) 8-, 9-, 10- atau 16-bit, dan independen satu sama lain, yang memungkinkan penerapan PWM multi-saluran. Dalam dokumentasi teknis, banyak halaman yang dikhususkan untuk mode ini, karena kompleksitas, keserbagunaan, dan kerumitannya. Penggunaan paling sederhana dari mode ini untuk pemutaran audio akan dibahas secara singkat di Bab 22 sehubungan dengan sinyal suara. Perhatikan bahwa sintesis suara bukan satu-satunya atau bahkan tujuan mode PWM dengan prioritas tertinggi; mode PWM juga dapat digunakan untuk mengatur daya atau arus (misalnya, saat mengisi daya baterai), mengendalikan motor, memperbaiki sinyal, dan konversi digital-ke-analog. .

Selain penghitung waktu, semua pengontrol AVR, tanpa kecuali, memiliki pengatur waktu Watchdog. Hal ini dimaksudkan terutama untuk mengeluarkan MK dari mode hemat energi setelah interval waktu tertentu, tetapi juga dapat digunakan untuk menghidupkan kembali MK secara darurat. Misalnya, jika pengoperasian program bergantung pada kedatangan sinyal eksternal, maka jika sinyal tersebut hilang (misalnya, karena putusnya saluran), MK dapat “hang”, dan pengatur waktu Watchdog akan mengeluarkannya. dari negara bagian ini.

Port serial

Port serial untuk bertukar data dengan perangkat eksternal adalah komponen terpenting dari setiap MK; tanpanya, “komunikasi” dengan dunia luar sangat terbatas. Mereka disebut sekuensial karena hanya satu bit yang ditransmisikan pada satu waktu (dalam beberapa kasus, transmisi dan penerimaan simultan dimungkinkan, namun tetap hanya satu bit pada satu waktu). Keuntungan paling penting dari port serial dibandingkan port paralel (ketika seluruh byte atau tetrad nibbles dipertukarkan secara bersamaan) adalah pengurangan jumlah koneksi. Namun ini bukan satu-satunya: secara paradoks, antarmuka serial memberikan keunggulan yang signifikan dibandingkan antarmuka paralel pada kecepatan tinggi, ketika penundaan saluran mulai memengaruhi kecepatan transmisi. Yang terakhir ini tidak dapat dibuat sama persis, dan inilah salah satu alasan mengapa antarmuka serial kini mulai mendominasi (contoh umumnya adalah USB dan FireWire sebagai pengganti COM, LPT dan SCSI, atau Serial ATA sebagai ganti IDE).

Pada perangkat mikrokontroler dengan volume data yang besar, tentu saja, kecepatan transfer menjadi perhatian kedua, tetapi jumlah kabel penghubung merupakan faktor yang sangat penting. Oleh karena itu, semua perangkat eksternal yang akan kita bahas dalam buku ini akan memiliki antarmuka serial.

Hampir semua port serial dapat disimulasikan dalam perangkat lunak menggunakan pin MCU biasa. Dahulu kala hal ini dilakukan bahkan dalam kasus noptoB yang paling populer - UART. Namun, sejak itu, MK telah memperoleh port serial perangkat keras, namun tidak berarti perlunya penggunaan mutlaknya. Kemudahan simulasi perangkat lunak port serial merupakan keuntungan lainnya.

Dari semua jenis port yang mungkin ada dalam AVR MCU, kami secara khusus akan memperhatikan UART-Universal Asynchronous Receiver-Transmitter, “universal asynchronous transceiver”. UART adalah bagian utama dari perangkat apa pun yang mendukung protokol RS-232, tetapi tidak hanya itu (bukan tanpa alasan bahwa ini "universal") - misalnya, standar industri RS-485 dan RS-422 juga diimplementasikan melalui UART , karena mereka berbeda dari RS-232 hanya dalam parameter kelistrikan dan kecepatan yang diizinkan, dan bukan dalam logika konstruksi umum. Komputer pribadi memiliki port COM yang beroperasi menggunakan protokol RS-232 yang sama, dan node UART juga merupakan bagian dasarnya.

Oleh karena itu, UART berfungsi sebagai jalur utama pertukaran data antara MK dan komputer. Perhatikan bahwa kurangnya port COM di sebagian besar model PC modern bukanlah halangan: ada adaptor USB-COM untuk ini, dan kartu tambahan dengan port COM dapat dimasukkan ke model desktop.

Catatan di pinggir

Mengapa hal ini sangat penting bagi kami? Faktanya adalah dengan menghubungkan tata letak perangkat ke komputer, meskipun pertukaran data tidak disediakan oleh fungsionalitas perangkat, akan lebih mudah untuk men-debug program hanya dengan memasukkan sementara operasi pengiriman di tempat yang tepat ke dalam program. nilai-nilai register yang terlibat ke PC dan menerimanya secara real time menggunakan beberapa -atau program emulator terminal. Ini jauh lebih nyaman daripada menguasai AVR Studio yang besar, dan bahkan dibundel dengan papan debugging yang mahal. Oleh karena itu, saran saya adalah segera membuat sendiri papan debugging yang berisi konektor pemrograman (lihat bab berikutnya) dan konverter level UART/RS-232 dengan konektor untuk menghubungkan kabel modem null (lihat Bab 21).

Cara menggunakan UART dalam praktiknya dibahas di Bab 21. Selain UART, hampir semua MCU AVR memiliki port serial yang paling sederhana - SPI (Serial Peripheral Interface). Prinsip perangkat SPI disebutkan dalam Bab 16. Kesederhanaan mendasarnya memainkan peran yang agak buruk: sulit untuk menemukan dua perangkat yang protokol SPI-nya benar-benar sama; biasanya pertukaran melalui port ini disertai dengan satu atau lain hal. lonceng dan peluit”. Perlu dicatat bahwa pemrograman AVR juga dilakukan melalui SPI, namun secara umum antarmuka ini dan SPI untuk pertukaran data adalah hal yang berbeda, meskipun dalam banyak kasus keduanya memiliki pin yang sama.

Namun dalam buku ini, di Bab 21, kita akan melihat antarmuka I^C yang lebih kompleks, meskipun lebih lambat, yang diperlukan lebih sering karena begitu banyak perangkat periferal yang bekerja melaluinya.

Kami akan mempertimbangkan beberapa komponen lain dari MK dari keluarga AVR (misalnya, ADC) saat kami menyajikan sirkuit spesifik - ini akan menjadi lebih jelas. Di sini kita akan menyelesaikan pengenalan panjang lebar kita tentang mikrokontroler dan beralih ke pertanyaan tentang bagaimana memprogramnya.

Hari ini kita akan mencoba menggunakan mikrokontroler yang lebih sederhana ATtiny2313 dan sambungkan ke layar LCD karakter yang berisi dua baris 16 karakter.

Kami akan menghubungkan layar dengan cara standar 4-bit.

Pertama, tentu saja kita mulai dengan mikrokontroler, karena kita sudah sangat familiar dengan tampilan dari pelajaran sebelumnya.

Mari buka lembar data pengontrol ATtiny2313 dan mari kita lihat pinoutnya

Kita melihat bahwa pengontrol ini ada dalam dua jenis kasing, tetapi karena saya mendapatkannya dalam paket DIP, kami akan mempertimbangkan versi kasing khusus ini, dan pada prinsipnya, keduanya tidak jauh berbeda, kecuali tampilannya, jadi berapa jumlahnya kakinya sama - masing-masing 20.

Karena ada 20 kaki dibandingkan dengan 28 kaki pengontrol ATMega8, yang telah kami kerjakan selama ini dan akan terus kami kerjakan, maka kemungkinannya juga akan lebih kecil.

Pada prinsipnya, semua yang dimiliki ATmega8 ada di sini, satu-satunya hal adalah cakar portnya lebih sedikit. Namun karena tugas yang kami hadapi adalah mencoba menghubungkannya melalui bus SPI dengan pengontrol lain, hal ini tidak membuat kami terlalu tertekan.

Ada beberapa perbedaan lain, tetapi perbedaannya kecil dan kami akan mengetahuinya sesuai kebutuhan.

Mari kita rakit rangkaian seperti ini (klik gambar untuk memperbesar gambar)

Layar terhubung ke pin port D. PD1 dan PD2 ke input kontrol, dan sisanya terhubung ke pin modul tampilan D4-D7.

Mari kita buat proyek dengan nama TINY2313_LCD, transfer semuanya ke dalamnya kecuali modul utama dari proyek untuk menghubungkan layar ke Atmega8.

Tentu saja, ada beberapa hal yang perlu diperbaiki. Untuk melakukan ini, Anda perlu mempelajari dengan cermat kaki mana yang terhubung dengan apa. Bus E pada tampilan terhubung ke PD2, dan bus RS terhubung ke PD1, jadi mari kita buat perubahan pada file LCD.h

#mendefinisikane1PORTD|=0b0000 01 00 // setel baris E ke 1

#mendefinisikane0PORTD&=0b1111 10 11 // setel baris E ke 0

#mendefinisikanrs1PORTD|=0b00000 01 0 // atur baris RS ke 1 (data)

#mendefinisikanrs0PORTD&=0b11111 10 1 // atur baris RS ke 0 (perintah)

Seperti yang bisa kita lihat dari huruf tebal, kami belum mengalami perubahan drastis seperti itu.

Sekarang masukan informasi. Disini kita menggunakan kaki-kaki PD3-PD6 yaitu digeser 1 poin dibandingkan koneksi ke Atmega8, jadi kita juga akan memperbaiki sesuatu di file tersebut LCD.c dalam fungsi sendhalfbyte

PORTD&=0b 1 0000 111; // hapus informasi pada input DB4-DB7, biarkan sisanya

Tapi itu belum semuanya. Sebelumnya kita menggeser data yang dikirimkan sebanyak 4, namun sekarang, karena perubahan di atas, kita hanya perlu menggesernya sebanyak 3. Oleh karena itu, pada fungsi yang sama kita juga akan mengoreksi baris pertama.

C<<=3 ;

Itu semua perubahannya. Setuju, mereka tidak terlalu bagus! Hal ini dicapai dengan fakta bahwa kami selalu mencoba menulis kode universal dan menggunakan substitusi makro. Jika kami tidak menghabiskan waktu untuk hal ini sekaligus, kami harus memperbaiki kode di hampir semua fungsi perpustakaan kami.

Pada modul utama, kita tidak menyentuh inisialisasi port D; biarkan seluruh modul masuk ke status keluaran, seperti pada pelajaran 12.

Mari kita coba merakit proyeknya dan lihat dulu hasilnya di Proteus, karena saya juga membuat proyek untuk itu, yang juga akan ada di arsip terlampir dengan proyek untuk Atmel Studio

Semuanya bekerja dengan baik untuk kami! Ini adalah bagaimana Anda dapat dengan cepat membuat ulang proyek untuk satu pengontrol ke pengontrol lainnya.

Proteus sangat bagus, tetapi selalu lebih baik jika melihat detail sebenarnya. Seluruh rangkaian dirakit di papan tempat memotong roti, karena saya tidak membuat atau merakit papan debug untuk pengontrol ini. Kami akan menghubungkan programmer melalui konektor standar seperti ini

Berikut diagram keseluruhannya

Semuanya standar di sini. Resistor penarik untuk RESET, dll.

Sekarang, sebelum mem-flash pengontrol di avrdude, kita perlu memilih pengontrol dan membaca memori flash-nya

Lalu buka tab FUSES dan atur sekring dengan benar. Karena kami tidak memiliki resonator kuarsa, kami memasang sekring dengan cara ini

Menghubungkan LED ke jalur port I/O

Setelah mempelajari materi ini, yang semuanya dijelaskan dengan sangat rinci dengan banyak contoh, Anda dapat dengan mudah menguasai dan memprogram port input/output mikrokontroler AVR.

  • Bagian 2. Menghubungkan LED ke jalur port I/O
  • Bagian 3. Menghubungkan transistor ke jalur port I/O
Kami akan mempertimbangkan contoh pada mikrokontroler ATMega8 .

Kami akan menulis programnya Atmel Studio 6.0 .

Kami akan meniru sirkuit di Proteus 7 Profesional .

Contoh pertama dalam mempelajari mikrokontroler adalah menghubungkan dan mengendalikan LED; ini adalah contoh paling sederhana dan jelas. Contoh ini telah menjadi contoh klasik dalam studi mikrokontroler, seperti program “Hello World!”. saat mempelajari bahasa pemrograman lain.
Arus maksimum yang dapat dilewati setiap port I/O adalah 40 mA.
Arus maksimum yang dapat dibawa oleh setiap jalur port I/O adalah 20 mA.
Sebelum menghubungkan suatu beban, termasuk LED, ke jalur port I/O, perlu Anda ketahui bahwa Anda dapat membakar mikrokontroler jika melebihi beban yang diizinkan pada jalur port I/O.
Untuk membatasi arus yang mengalir melalui jalur port I/O mikrokontroler, Anda perlu menghitung dan menghubungkan resistor.

Gambar: pinout LED.

Gambar: Menghubungkan anoda LED ke mikrokontroler.

Gambar: Menghubungkan katoda LED ke mikrokontroler.

Resistansi resistor pembatas arus yang terhubung ke saluran port input/output saat menghubungkan LED dihitung dengan rumus:

Di mana:
- Vs- tegangan catu daya;
- Vsp- penurunan tegangan pada jalur port I/O;
- Vd- penurunan tegangan langsung pada LED;
- PENGENAL- arus searah pada LED;
- buku- Koefisien keandalan LED;

Contoh:
- tegangan catu daya - 5V;
- penurunan tegangan langsung pada LED – 2B ;
10mA (Diambil dari lembar data ke LED);
- koefisien keandalan robot LED – 75% (Diambil dari lembar data ke LED);
- penurunan tegangan pada jalur port I/O – 0,5V (Diambil dari datasheet ke mikrokontroler: Vol(output tegangan rendah) – jika arus masuk, dan Voh (output tegangan tinggi) – jika arus keluar);

Demikianlah nilai resistornya R = 166,66 Ohm, nilai resistensi terdekat yang lebih tinggi dipilih.

Jika tegangan maju LED tidak diketahui, maka hambatannya dapat dihitung menggunakan hukum Ohm.

Di mana:
- kamu- tegangan diterapkan ke bagian rangkaian;
- SAYA

Contoh:
4.5V;
- arus pengenal jalur port I/O – 20mA.

Setelah menentukan nilai resistor R, perlu untuk menghitung kekuatannya P, diukur dalam watt, yang akan dilepaskan pada resistor dalam bentuk panas ketika arus mengalir dalam rangkaian.

Di mana:
- kamu– tegangan yang diterapkan pada suatu bagian sirkit;
- SAYA- arus terukur dari jalur port I/O.

Contoh:
- tegangan yang diterapkan pada suatu bagian rangkaian – 4.5V;
- arus maju pada LED – 20mA.

Setelah menghitung daya yang dialokasikan ke resistor, kami memilih nilai daya resistor terdekat yang lebih tinggi. Jika disipasi daya resistor tidak mencukupi, resistor mungkin gagal.

- menghubungkan anoda LED berdaya rendah ke jalur port I/O:

#termasuk // Program utama int main(void) ( // Atur port input/output DDRC = 0b11111111; // Atur semua bit port C ke mode "Output" PORTC = 0b11111111; // Atur semua bit port C untuk mencatat "1" (Tegangan pada keluaran port sama dengan Vcc) // Perulangan abadi sementara (1) ( ) )

- menghubungkan LED berdaya rendah dengan katoda ke jalur port I/O:

// Sertakan perpustakaan eksternal #include #termasuk // Program utama int main(void) ( // Konfigurasikan port input/output DDRC = 0b11111111; // Konfigurasikan semua bit port C ke mode "Output" PORTC = 0b00000000; // Atur semua bit port C ke log "0" (Pada output port tegangannya sama dengan GND) // Loop abadi sementara (1) ( ) )

- menghubungkan LED berdaya rendah dengan anoda dan katoda ke jalur port I/O:

// Sertakan perpustakaan eksternal #include #termasuk // Program utama int main(void) ( // Konfigurasikan port input/output DDRD = 0b11111111; // Konfigurasikan semua bit port D ke mode "Output" PORTD = 0b11111111; // Atur semua bit port D ke log "1" (Pada output port tegangannya sama dengan Vcc) DDRC = 0b11111111; //Atur semua bit port C ke mode “Output” PORTC = 0b00000000; //Atur semua bit port C ke logika “ 0” (Pada output port tegangannya sama dengan GND) // Loop abadi sementara (1) ( ) )