Isi kandungan:

Tutorial Penyusun AVR 3: 9 Langkah
Tutorial Penyusun AVR 3: 9 Langkah

Video: Tutorial Penyusun AVR 3: 9 Langkah

Video: Tutorial Penyusun AVR 3: 9 Langkah
Video: Mempelajari komponen penting pada genset (AVR) MX341 Series 2024, November
Anonim
Tutorial Penyusun AVR 3
Tutorial Penyusun AVR 3

Selamat datang ke tutorial nombor 3!

Sebelum kita memulakan, saya ingin mengemukakan falsafah. Jangan takut untuk bereksperimen dengan litar dan kod yang kami bina dalam tutorial ini. Tukar kabel sekitar, tambahkan komponen baru, keluarkan komponen, ubah baris kod, tambahkan baris baru, hapus garis, dan lihat apa yang berlaku! Sangat sukar untuk memecahkan apa-apa dan jika anda melakukannya, siapa yang peduli? Tidak ada yang kami gunakan, termasuk mikrokontroler, yang sangat mahal dan selalu mendidik untuk melihat bagaimana keadaan boleh gagal. Anda bukan sahaja akan mengetahui apa yang tidak boleh dilakukan pada masa akan datang, tetapi yang lebih penting lagi, anda akan mengetahui mengapa tidak melakukannya. Sekiranya anda seperti saya, ketika anda masih kecil dan anda mendapat mainan baru, tidak lama sebelum anda memilikinya untuk melihat apa yang membuatnya sesuai? Kadang-kadang mainan itu rosak teruk tetapi tidak ada masalah besar. Membiarkan kanak-kanak meneroka rasa ingin tahunya hingga ke mainan yang rosak itulah yang menjadikannya seorang saintis atau jurutera dan bukannya mesin cuci pinggan mangkuk.

Hari ini kita akan memasang litar yang sangat mudah dan kemudian memasukkan teori ini dengan sedikit berat. Maaf tentang ini, tetapi kami memerlukan alat! Saya berjanji kita akan menebusnya dalam tutorial 4 di mana kita akan membuat beberapa bangunan litar yang lebih serius dan hasilnya akan cukup hebat. Walau bagaimanapun, cara yang anda perlukan untuk melakukan semua tutorial ini adalah dengan cara yang sangat perlahan dan kontemplatif. Sekiranya anda hanya membajak, membina litar, menyalin dan menampal kodnya, dan menjalankannya, pasti, ia akan berfungsi, tetapi anda tidak akan belajar apa-apa. Anda perlu memikirkan setiap baris. Jeda sebentar. Percubaan. Buat. Sekiranya anda melakukannya dengan cara itu maka pada akhir tutorial ke-5, anda akan mula membina barang-barang menarik dan tidak memerlukan bimbingan lagi. Jika tidak, anda hanya menonton dan bukannya belajar dan membuat.

Walau apa pun, cukup falsafah, mari kita mulakan!

Dalam tutorial ini, anda memerlukan:

  1. papan prototaip anda
  2. LED
  3. wayar penyambung
  4. perintang sekitar 220 hingga 330 ohm
  5. Manual Set Arahan: www.atmel.com/images/atmel-0856-avr-instruction-se…
  6. Lembaran Data: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
  7. pengayun kristal yang berbeza (pilihan)

Berikut adalah pautan ke koleksi tutorial lengkap:

Langkah 1: Membina Litar

Membina Litar
Membina Litar

Litar dalam tutorial ini sangat mudah. Pada dasarnya kita akan menulis program "blink" jadi yang kita perlukan adalah yang berikut.

Sambungkan LED ke PD4, kemudian ke perintang 330 ohm, kemudian ke Ground. i.e.

PD4 - LED - R (330) - GND

dan itu sahaja!

Teorinya akan sukar untuk dilakukan walaupun…

Langkah 2: Mengapa Kita Perlu Komen dan Fail M328Pdef.inc?

Saya rasa kita harus mulakan dengan menunjukkan mengapa fail penyertaan dan komen berguna. Tidak satu pun dari mereka yang benar-benar diperlukan dan anda boleh menulis, memasang, dan memuat naik kod dengan cara yang sama tanpa mereka dan ia akan berjalan dengan baik (walaupun tanpa fail yang disertakan, anda mungkin mendapat beberapa aduan dari assembler - tetapi tidak ada kesalahan)

Inilah kod yang akan kami tulis hari ini, kecuali bahawa saya telah membuang komen dan fail yang disertakan:

.peranti ATmega328P

.org 0x0000 jmp a.org 0x0020 jmp ea: ldi r16, 0x05 out 0x25, r16 ldi r16, 0x01 sts 0x6e, r16 sei clr r16 out 0x26, r16 sbi 0x0a, 0x04 sbi 0x0b, 0x04 b: sbi 0x0b, 0x0b, cx cbi 0x0b, 0x04 rcall c rjmp bc: clr r17 d: cpi r17, 0x1e brne d ret e: inc r17 cpi r17, 0x3d brne PC + 2 clr r17 reti

cukup sederhana kan? Haha. Sekiranya anda mengumpulkan dan memuat naik fail ini, anda akan menyebabkan LED berkelip pada kadar 1 berkelip sesaat dengan berkelip bertahan 1/2 saat dan jeda antara berkelip bertahan 1/2 saat.

Walau bagaimanapun, melihat kod ini hampir tidak memberi pencerahan. Sekiranya anda menulis kod seperti ini anda dan ingin mengubahnya atau menggunakan semula pada masa akan datang anda akan menghadapi masa yang sukar.

Oleh itu, mari masukkan komen dan masukkan fail supaya kita dapat memahaminya.

Langkah 3: Blink.asm

Inilah kod yang akan kita bincangkan hari ini:

;************************************

; ditulis oleh: 1o_o7; Tarikh:; versi: 1.0; fail disimpan sebagai: blink.asm; untuk AVR: atmega328p; kekerapan jam: 16MHz (pilihan); ************************************; Fungsi program: ---------------------; mengira detik dengan mengedipkan LED;; PD4 - LED - R (330 ohm) - GND;; --------------------------------------.nolist.include "./m328Pdef.inc".list; ==============; Perisytiharan:.def temp = r16.def overflows = r17.org 0x0000; memori (PC) lokasi pengendali semula rjmp Tetapkan semula; jmp berharga 2 kitaran cpu dan kos rjmp hanya 1; jadi melainkan anda perlu melonjak lebih daripada 8k bait; anda hanya memerlukan rjmp. Oleh itu, sebilangan pengawal mikro sahaja; mempunyai rjmp dan bukan jmp.org 0x0020; lokasi memori pengendali limpahan Timer0 rjmp overflow_handler; pergi ke sini jika gangguan timer0 overflow berlaku; ============ Reset: ldi temp, 0b00000101 out TCCR0B, temp; tetapkan Jam Pemilih Jam CS00, CS01, CS02 hingga 101; ini meletakkan Timer Counter0, TCNT0 ke mod FCPU / 1024; jadi ia berdetak pada CPU freq / 1024 ldi temp, 0b00000001 sts TIMSK0, temp; tetapkan bit Timer Overflow Interrupt Enable (TOIE0); dari Timer Interrupt Mask Register (TIMSK0) sei; aktifkan gangguan global - bersamaan dengan "sbi SREG, I" clr temp out TCNT0, temp; mulakan Pemasa / Pembilang ke 0 sbi DDRD, 4; tetapkan PD4 ke output; ======================; Badan utama program: berkedip: sbi PORTD, 4; hidupkan LED pada kelewatan PD4 rcall; kelewatan akan menjadi 1/2 cbi PORTD kedua, 4; matikan LED pada kelewatan PD4 rcall; kelewatan akan berkedip 1/2 saat rjmp; gelung kembali ke kelewatan permulaan: limpahan clr; tetapkan limpahan ke 0 sec_count: limpahan cpi, 30; bandingkan jumlah limpahan dan 30 br_sec_count; cabang ke belakang ke jumlah_kira jika tidak sama ret; jika 30 limpahan berlaku kembali ke overflow_handler berkelip: inc overflows; tambah 1 pada limpahan limpahan cpi limpahan, 61; bandingkan dengan 61 brne PC + 2; Kaunter Program + 2 (langkau baris seterusnya) jika tidak sama limpahan clr; jika 61 limpahan berlaku, tetapkan semula kaunter ke sifar reti; kembali dari mengganggu

Seperti yang anda lihat, komen saya sedikit lebih ringkas sekarang. Setelah kita mengetahui apa perintah dalam set arahan, kita tidak perlu menjelaskannya dalam komen. Kita hanya perlu menjelaskan apa yang berlaku dari sudut pandangan program.

Kami akan membincangkan apa yang dilakukan semua ini secara berasingan, tetapi pertama-tama mari kita cuba mendapatkan perspektif global. Badan utama program berfungsi seperti berikut.

Mula-mula kita menetapkan bit 4 PORTD dengan "sbi PORTD, 4" ini menghantar 1 ke PD4 yang meletakkan voltan ke 5V pada pin itu. Ini akan menyalakan LED. Kami kemudian melompat ke subrutin "delay" yang mengira 1/2 saat (kami akan menerangkan bagaimana ia melakukannya kemudian). Kami kemudian kembali berkelip dan membersihkan bit 4 pada PORTD yang menetapkan PD4 hingga 0V dan dengan itu mematikan LED. Kami kemudian menunda selama 1/2 saat lagi, dan kemudian kembali ke awal berkelip lagi dengan "rjmp blink".

Anda harus menjalankan kod ini dan melihat bahawa ia melakukan apa yang sepatutnya.

Dan di sana anda memilikinya! Itulah semua kod ini dilakukan secara fizikal. Mekanik dalaman apa yang dilakukan oleh mikrokontroler sedikit lebih terlibat dan itulah sebabnya kita melakukan tutorial ini. Oleh itu mari kita membincangkan setiap bahagian secara bergiliran.

Langkah 4: Arahan Assembler.org

Kami sudah mengetahui arahan arahan pemasangan.nolist,.list,.include, dan.def dari tutorial sebelumnya, jadi mari kita lihat pada 4 baris kod yang muncul selepas itu:

.org 0x0000

jmp Tetapkan semula.org 0x0020 jmp overflow_handler

Pernyataan.org memberitahu assembler di mana di "Program Memory" untuk meletakkan pernyataan seterusnya. Ketika program anda dijalankan, "Program Counter" (disingkat PC) berisi alamat baris semasa yang sedang dijalankan. Jadi dalam kes ini ketika PC berada di 0x0000, ia akan melihat arahan "jmp Reset" berada di lokasi memori tersebut. Sebab kami ingin meletakkan jmp Reset di lokasi tersebut adalah kerana ketika program dimulakan, atau cip diset semula, PC mula menjalankan kod di tempat ini. Jadi, seperti yang kita lihat, kita baru saja menyuruhnya segera "melompat" ke bahagian berlabel "Reset". Mengapa kita berbuat demikian? Ini bermaksud bahawa dua baris terakhir di atas hanya dilangkau! Kenapa?

Itulah tempat yang menarik. Anda sekarang perlu membuka pemidang pdf dengan lembar data ATmega328p penuh yang saya tunjuk pada halaman pertama tutorial ini (sebab itulah item 4 di bahagian "anda akan memerlukan"). Sekiranya skrin anda terlalu kecil, atau terlalu banyak tetingkap yang sudah dibuka (seperti yang berlaku pada saya), anda boleh melakukan apa yang saya lakukan dan meletakkannya di Ereader, atau telefon Android anda. Anda akan menggunakannya sepanjang masa jika anda merancang untuk menulis kod pemasangan. Perkara yang menarik adalah bahawa semua mikrokontroler disusun dengan cara yang sangat serupa dan oleh itu, setelah anda terbiasa membaca lembaran data dan pengekodan daripadanya, anda akan merasa hampir remeh untuk melakukan perkara yang sama untuk mikrokontroler yang berbeza. Oleh itu, kita sebenarnya belajar bagaimana menggunakan semua mikrokontroler dalam arti dan bukan hanya atmega328p.

Baiklah, beralih ke halaman 18 dalam lembar data dan lihat Gambar 8-2.

Ini adalah bagaimana Memori Program dalam mikrokontroler disiapkan. Anda dapat melihat bahawa ia bermula dengan alamat 0x0000 dan dipisahkan menjadi dua bahagian; bahagian flash aplikasi dan bahagian flash flash. Sekiranya anda merujuk sebentar ke halaman 277 jadual 27-14 anda akan melihat bahawa bahagian flash aplikasi mengambil lokasi dari 0x0000 hingga 0x37FF dan bahagian flash flash mengambil lokasi yang tersisa dari 0x3800 hingga 0x3FFF.

Latihan 1: Berapa banyak lokasi yang terdapat dalam memori Program? I. E. tukar 3FFF ke perpuluhan dan tambah 1 sejak kita mula mengira pada 0. Oleh kerana setiap lokasi memori selebar 16 bit (atau 2 bait) berapakah jumlah keseluruhan bait memori? Sekarang ubah ini menjadi kilobyte, ingat bahawa terdapat 2 ^ 10 = 1024 bait dalam satu kilobyte. Bahagian kilat but bermula dari 0x3800 hingga 0x37FF, berapa kilobyte ini? Berapa banyak kilobytes memori yang masih ada untuk kita gunakan untuk menyimpan program kita? Dengan kata lain, seberapa besar program kita? Akhirnya, berapa banyak baris kod yang boleh kita miliki?

Baiklah, setelah kita mengetahui semua tentang organisasi memori program flash, mari teruskan perbincangan kami mengenai pernyataan.org. Kami melihat bahawa lokasi memori pertama 0x0000 mengandungi arahan kami untuk melompat ke bahagian kami yang kami beri label Reset. Sekarang kita melihat apa yang dilakukan oleh pernyataan ".org 0x0020". Ia mengatakan bahawa kami mahu arahan pada baris seterusnya diletakkan di lokasi memori 0x0020. Arahan yang telah kami letakkan adalah melompat ke bahagian dalam kod kami yang telah kami labelkan "overflow_handler" … sekarang mengapa kita menuntut agar lompatan ini ditempatkan di lokasi memori 0x0020? Untuk mengetahui, kami beralih ke halaman 65 dalam lembar data dan melihat Jadual 12-6.

Jadual 12-6 adalah jadual "Reset dan Interrupt Vectors" dan ia menunjukkan dengan tepat ke mana PC akan pergi ketika menerima "interrupt". Contohnya, jika anda melihat nombor Vektor 1. "Sumber" gangguan adalah "RESET" yang ditakrifkan sebagai "Pin Luaran, Reset Power-on, Reset Brown-out, dan reset sistem Watchdog" yang bermaksud, jika ada perkara tersebut berlaku pada mikrokontroler kita, PC akan mula menjalankan program kita di lokasi memori program 0x0000. Bagaimana dengan arahan.org kami? Baiklah, kami meletakkan perintah di lokasi memori 0x0020 dan jika anda melihat ke bawah jadual anda akan melihat bahawa jika berlaku limpahan Timer / Counter0 (datang dari TIMER0 OVF) ia akan melaksanakan apa sahaja yang ada di lokasi 0x0020. Oleh itu, setiap kali perkara itu berlaku, PC akan melompat ke tempat yang dilabelkan "overflow_handler". Sejuk kan? Anda akan melihat sebentar mengapa kami melakukan ini, tetapi pertama-tama mari kita selesaikan langkah tutorial ini dengan mengetepikan.

Sekiranya kita ingin menjadikan kod kita lebih kemas dan rapi, kita harus betul-betul mengganti 4 baris yang sedang kita bincangkan dengan yang berikut (lihat halaman 66):

.org 0x0000

tetapkan semula rjmp; PC = 0x0000 reti; PC = 0x0002 reti; PC = 0x0004 reti; PC = 0x0006 reti; PC = 0x0008 reti; PC = 0x000A… reti; PC = 0x001E jmp overflow_handler: PC = 0x0020 reti: PC = 0x0022… reti; PC = 0x0030 reti; PC = 0x0032

Oleh itu, sekiranya gangguan yang diberikan berlaku, ia hanya akan "reti" yang bermaksud "kembali dari gangguan" dan tidak ada yang lain berlaku. Tetapi jika kita tidak pernah "Aktifkan" pelbagai gangguan ini, maka tidak akan digunakan dan kita boleh meletakkan kod program di tempat ini. Dalam program "blink.asm" kami sekarang, kami hanya akan mengaktifkan timer0 overflow interrupt (dan tentu saja gangguan reset yang selalu diaktifkan) dan oleh itu kami tidak akan mengganggu yang lain.

Bagaimana kita "mengaktifkan" timer0 overflow mengganggu? … itu adalah topik langkah seterusnya dalam tutorial ini.

Langkah 5: Pemasa / Kaunter 0

Pemasa / Kaunter 0
Pemasa / Kaunter 0

Lihat gambar di atas. Ini adalah proses membuat keputusan "PC" ketika pengaruh luar "mengganggu" aliran program kami. Perkara pertama yang dilakukannya apabila mendapat isyarat dari luar bahawa gangguan berlaku ialah ia memeriksa untuk mengetahui apakah kita telah menetapkan bit "interrupt enabled" untuk jenis gangguan tersebut. Sekiranya kita belum melakukannya, maka ia terus menjalankan baris kod seterusnya. Sekiranya kita telah menetapkan bit pengaktifan gangguan tertentu (sehingga ada 1 di lokasi bit itu dan bukan 0), ia kemudian akan memeriksa sama ada kita telah mengaktifkan "gangguan global" atau tidak, jika tidak, ia akan kembali ke baris seterusnya kod dan teruskan. Sekiranya kita telah mengaktifkan gangguan global juga, maka ia akan pergi ke lokasi Memori Program jenis gangguan tersebut (seperti yang ditunjukkan dalam Jadual 12-6) dan melaksanakan perintah apa pun yang telah kita letakkan di sana. Oleh itu, mari kita lihat bagaimana kita melaksanakan semua ini dalam kod kita.

Bahagian Reset berlabel kod kami bermula dengan dua baris berikut:

Tetapkan semula:

ldi temp, 0b00000101 keluar TCCR0B, temp

Seperti yang sudah kita ketahui, ini memuatkan temp (iaitu R16) nombor yang segera diikuti, yaitu 0b00000101. Kemudian ia menuliskan nombor ini ke daftar yang disebut TCCR0B menggunakan perintah "keluar". Apa daftar ini? Baiklah, mari kita pergi ke halaman 614 lembar data. Ini berada di tengah-tengah jadual yang merangkum semua daftar. Di alamat 0x25 anda akan menemui TCCR0B. (Sekarang anda tahu dari mana garis "keluar 0x25, r16" berasal dari versi kod saya yang tidak dikomentari). Kami melihat segmen kod di atas bahawa kami telah menetapkan bit ke-0 dan bit ke-2 dan membersihkan semua yang lain. Dengan melihat jadual anda dapat melihat bahawa ini bermakna kami telah menetapkan CS00 dan CS02. Sekarang mari kita pergi ke bab dalam lembar data yang disebut "8-bit Timer / Counter0 with PWM". Khususnya, pergi ke halaman 107 bab itu. Anda akan melihat keterangan yang sama mengenai daftar "Timer / Counter Control Register B" (TCCR0B) yang baru kita lihat dalam jadual ringkasan daftar (jadi kita boleh datang terus ke sini, tetapi saya mahu anda melihat cara menggunakan jadual ringkasan untuk rujukan masa depan). Lembar data terus memberikan penerangan mengenai setiap bit dalam daftar tersebut dan apa yang mereka lakukan. Kami akan melupakan semua itu buat masa ini dan mengubah halaman ke Jadual 15-9. Jadual ini menunjukkan "Penerangan Jam Pilih Bit". Sekarang lihat jadual itu sehingga anda menemui garis yang sesuai dengan bit yang baru kami tetapkan dalam daftar itu. Garis itu menyatakan "clk / 1024 (dari prescaler)". Maksudnya ialah kita mahu Timer / Counter0 (TCNT0) mencentang pada kadar yang merupakan frekuensi CPU dibahagi dengan 1024. Oleh kerana mikrokontroler kita diberi makan oleh pengayun kristal 16MHz, ini bermaksud kadar yang CPU kita laksanakan adalah 16 juta arahan sesaat. Jadi kadar yang akan dicentang oleh kaunter TCNT0 ialah 16 juta / 1024 = 15625 kali sesaat (cubalah dengan bit pilih jam yang berbeza dan lihat apa yang berlaku - ingat falsafah kami?). Mari simpan nombor 15625 di fikiran kita untuk kemudian dan beralih ke dua baris kod seterusnya:

ldi temp, 0b00000001

sts TIMSK0, temp

Ini menetapkan bit ke-0 register yang disebut TIMSK0 dan membersihkan semua yang lain. Sekiranya anda melihat halaman 109 dalam lembar data, anda akan melihat bahawa TIMSK0 adalah singkatan dari "Timer / Counter Interrupt Mask Register 0" dan kod kami telah menetapkan bit ke-0 yang diberi nama TOIE0 yang bermaksud "Timer / Counter0 Overflow Interrupt Enable" … Ada! Sekarang anda melihat semua ini. Kami sekarang mempunyai "interrupt allow bit set" seperti yang kita mahukan dari keputusan pertama dalam gambar kita di bahagian atas. Jadi sekarang yang harus kita lakukan adalah mengaktifkan "gangguan global" dan program kita akan dapat bertindak balas terhadap jenis gangguan ini. Kami akan mengaktifkan gangguan global tidak lama lagi, tetapi sebelum kami melakukannya, anda mungkin telah keliru dengan sesuatu.. mengapa saya menggunakan arahan "sts" untuk menyalin ke daftar TIMSK0 dan bukannya "keluar" biasa?

Setiap kali anda melihat saya menggunakan arahan yang belum pernah anda lihat sebelum perkara pertama yang harus anda lakukan ialah beralih ke halaman 616 dalam lembar data. Ini adalah "Ringkasan Set Instruksi". Sekarang cari arahan "STS" yang saya gunakan. Ia mengatakan ia mengambil nombor dari daftar R (kami menggunakan R16) dan lokasi "Simpan terus ke SRAM" k (dalam kes kami diberikan oleh TIMSK0). Oleh itu, mengapa kita harus menggunakan "sts" yang memerlukan 2 kitaran jam (lihat lajur terakhir dalam jadual) untuk disimpan dalam TIMSK0 dan kita hanya memerlukan "keluar", yang hanya memerlukan satu pusingan jam, untuk menyimpan di TCCR0B sebelumnya? Untuk menjawab soalan ini, kami perlu kembali ke jadual ringkasan daftar kami di halaman 614. Anda melihat bahawa daftar TCCR0B berada di alamat 0x25 tetapi juga di (0x45) kan? Ini bermaksud bahawa itu adalah daftar di SRAM, tetapi juga merupakan jenis daftar tertentu yang disebut "port" (atau daftar i / o). Sekiranya anda melihat jadual ringkasan arahan di sebelah perintah "keluar" anda akan melihat bahawa ia mengambil nilai dari "register kerja" seperti R16 dan mengirimkannya ke PORT. Oleh itu, kita dapat menggunakan "keluar" semasa menulis kepada TCCR0B dan menyelamatkan diri kita satu pusingan jam. Tetapi sekarang cari TIMSK0 di jadual daftar. Anda melihat bahawa ia mempunyai alamat 0x6e. Ini berada di luar jangkauan port (yang hanya merupakan lokasi SRAM 0x3F pertama) dan oleh itu anda harus kembali menggunakan perintah sts dan mengambil dua kitaran jam CPU untuk melakukannya. Sila baca Catatan 4 di akhir jadual ringkasan arahan di halaman 615 sekarang. Perhatikan juga bahawa semua port input dan output kami, seperti PORTD terletak di bahagian bawah jadual. Sebagai contoh, PD4 adalah bit 4 di alamat 0x0b (sekarang anda melihat dari mana semua barang 0x0b berasal dari kod saya yang tidak dikomentari!).. baiklah, soalan cepat: adakah anda menukar "sts" menjadi "keluar" dan melihat apa berlaku? Ingatlah falsafah kami! pecahkan ia! jangan hanya mengambil kata-kata saya untuk perkara.

Baiklah, sebelum kita beralih, beralih ke halaman 19 dalam lembar data selama satu minit. Anda melihat gambar memori data (SRAM). 32 register pertama di SRAM (dari 0x0000 hingga 0x001F) adalah "register kerja tujuan umum" R0 hingga R31 yang kami gunakan sepanjang masa sebagai pemboleh ubah dalam kod kami.64 daftar seterusnya adalah port I / O hingga 0x005f (iaitu yang kita bicarakan yang mempunyai alamat yang tidak di-bracket di sebelahnya di dalam jadual daftar yang mana kita dapat menggunakan perintah "keluar" dan bukannya "sts") Akhirnya bahagian SRAM seterusnya mengandungi semua daftar lain dalam jadual ringkasan untuk mengatasi 0x00FF, dan terakhir selebihnya adalah SRAM dalaman. Sekarang dengan cepat, mari beralih ke halaman 12 sebentar. Di sana anda melihat jadual "register kerja tujuan umum" yang selalu kami gunakan sebagai pemboleh ubah kami. Anda melihat garis tebal antara nombor R0 hingga R15 dan kemudian R16 hingga R31? Garis itulah sebabnya mengapa kita selalu menggunakan R16 sebagai yang terkecil dan saya akan memasukkannya sedikit lagi dalam tutorial seterusnya di mana kita juga memerlukan tiga daftar alamat tidak langsung 16-bit, X, Y, dan Z. Saya tidak akan masuk ke dalamnya walaupun sejak kita tidak memerlukannya sekarang dan kita cukup tersekat di sini.

Balikkan satu halaman ke halaman 11 lembaran data. Anda akan melihat gambarajah daftar SREG di bahagian atas kanan? Anda melihat bahawa bit 7 dari daftar itu disebut "I". Sekarang turun halaman dan baca keterangan Bit 7…. ya! Ini adalah bit Global Interrupt Enable. Itulah yang perlu kita atur agar dapat mengambil keputusan kedua dalam rajah kita di atas dan membiarkan gangguan masa / overflow terganggu dalam program kita. Oleh itu, baris seterusnya program kami harus membaca:

sbi SREG, Saya

yang menetapkan bit disebut "I" dalam daftar SREG. Namun, daripada ini kami telah menggunakan arahan

sei

sebaliknya. Bit ini sering dilakukan dalam program sehingga mereka hanya membuat kaedah yang lebih mudah untuk melakukannya.

Baik! Sekarang kita telah menyiapkan gangguan limpahan sehingga "jmp overflow_handler" kita akan dilaksanakan setiap kali berlaku.

Sebelum kita teruskan, lihatlah daftar SREG (Status Status) kerana ia sangat penting. Baca apa yang diwakili oleh setiap bendera. Khususnya, banyak arahan yang kami gunakan akan menetapkan dan memeriksa bendera ini sepanjang masa. Sebagai contoh, di kemudian hari kita akan menggunakan perintah "CPI" yang bermaksud "membandingkan segera". Lihat jadual ringkasan arahan untuk arahan ini dan perhatikan berapa banyak bendera yang ditetapkannya di lajur "bendera". Ini semua bendera di SREG dan kod kami akan menetapkannya dan memeriksanya secara berterusan. Anda akan melihat contohnya sebentar lagi. Akhirnya bahagian terakhir kod ini adalah:

clr temp

keluar TCNT0, temp sbi DDRD, 4

Baris terakhir di sini cukup jelas. Ia hanya menetapkan bit ke-4 Daftar Arah Data untuk PortD menyebabkan PD4 menjadi OUTPUT.

Yang pertama menetapkan suhu berubah menjadi sifar dan kemudian menyalinnya ke daftar TCNT0. TCNT0 adalah Pemasa / Pembilang0 kami. Ini menjadikannya sifar. Sebaik sahaja PC melaksanakan baris ini, pemasa 0 akan bermula pada sifar dan dikira pada kadar 15625 kali setiap saat. Masalahnya ialah ini: TCNT0 adalah daftar "8-bit" bukan? Jadi apakah nombor terbesar yang boleh dimiliki oleh daftar 8-bit? Baiklah 0b11111111 itu. Ini adalah nombor 0xFF. Yang manakah 255. Oleh itu, anda melihat apa yang berlaku? Pemasa zipping terus meningkat 15625 kali sesaat dan setiap kali mencapai 255 ia "melimpah" dan kembali ke 0 lagi. Pada masa yang sama apabila ia kembali ke sifar, ia akan menghantar isyarat Timer Overflow Interrupt. PC mendapat ini dan anda tahu apa yang dilakukannya sekarang? Yap. Ia pergi ke Lokasi Memori Program 0x0020 dan melaksanakan arahan yang terdapat di sana.

Hebat! Sekiranya anda masih bersama saya maka anda adalah superhero yang tidak kenal lelah! Mari teruskan …

Langkah 6: Penangan Limpahan

Oleh itu mari kita anggap bahawa daftar pemasa / penghitung0 baru sahaja meluap. Kami sekarang tahu bahawa program ini menerima isyarat gangguan dan menjalankan 0x0020 yang memberitahu Kaunter Program, PC untuk melompat ke label "overflow_handler" berikut adalah kod yang kami tulis selepas label itu:

overflow_handler:

inc overflows cpi overflows, 61 brne PC + 2 clr overflows reti

Perkara pertama yang dilakukannya ialah meningkatkan pemboleh ubah "overflows" (yang merupakan nama kami untuk daftar kerja tujuan umum R17) kemudian "membandingkan" kandungan limpahan dengan nombor 61. Cara kerja arahan cpi adalah bahawa ia hanya mengurangkan dua nombor dan jika hasilnya adalah sifar, ia akan menetapkan bendera Z di daftar SREG (saya memberitahu anda bahawa kita akan selalu melihat daftar ini). Sekiranya kedua-dua nombor itu sama maka bendera Z akan menjadi 1, jika kedua-dua nombor itu tidak sama maka ia akan menjadi 0.

Baris seterusnya mengatakan "brne PC + 2" yang bermaksud "cabang jika tidak sama". Pada dasarnya, ia menandakan bendera Z di SREG dan jika BUKAN satu (iaitu dua nombor tidak sama, jika sama, bendera sifar akan ditetapkan) cawangan PC ke PC + 2, yang bermaksud melangkau yang berikutnya baris dan terus ke "reti" yang kembali dari gangguan ke tempat apa pun yang ada dalam kod ketika gangguan tiba. Sekiranya arahan brne menjumpai 1 dalam bit bendera sifar, ia tidak akan bercabang dan sebaliknya, ia akan terus ke baris seterusnya yang akan melimpah melimpahkannya semula ke 0.

Apakah hasil bersih dari semua ini?

Baiklah kita melihat bahawa setiap kali terdapat overflow pemasa, pengendali ini akan meningkatkan nilai "overflow" oleh satu. Oleh itu, pemboleh ubah "limpahan" adalah mengira jumlah limpahan semasa ia berlaku. Apabila bilangannya mencapai 61, kita menetapkannya semula menjadi sifar.

Sekarang mengapa di dunia kita melakukannya?

Mari lihat. Ingat bahawa kelajuan jam untuk CPU kami adalah 16MHz dan kami "prescaled" menggunakan TCCR0B sehingga pemasa hanya dikira pada kadar 15625 kiraan sesaat kan? Dan setiap kali pemasa mencapai kiraan 255, ia akan melimpah. Jadi itu bermakna ia melimpah 15625/256 = 61.04 kali sesaat. Kami mengawasi jumlah limpahan dengan pemboleh ubah "limpahan" kami dan kami membandingkan jumlah itu dengan 61. Oleh itu, kami melihat bahawa "limpahan" akan sama dengan 61 sekali setiap saat! Oleh itu, pengendali kami akan menetapkan semula "limpahan" menjadi sifar sekali setiap saat. Oleh itu, jika kita hanya memantau pemboleh ubah "limpahan" dan perhatikan setiap kali ia berubah menjadi sifar, kita akan mengira detik demi detik dalam masa nyata (Perhatikan bahawa dalam tutorial seterusnya kita akan menunjukkan cara mendapatkan yang lebih tepat kelewatan dalam milisaat dengan cara yang sama dengan rutin "kelewatan" Arduino berfungsi).

Sekarang kita telah "mengatasi" gangguan masa yang berlebihan. Pastikan anda memahami bagaimana ini berfungsi dan teruskan ke langkah seterusnya di mana kita memanfaatkan fakta ini.

Langkah 7: Kelewatan

Sekarang kita telah melihat bahawa rutin pengendali "overflow_handler" interrupt overflow timer kita akan menetapkan pemboleh ubah "overflow" menjadi sifar sekali setiap saat, kita dapat menggunakan fakta ini untuk merancang subrutin "delay".

Lihatlah kod berikut dari bawah kelewatan kami: label

kelewatan:

clr overflows sec_count: limpahan cpi, 30 brne sec_count ret

Kami akan memanggil subrutin ini setiap kali kami memerlukan kelewatan dalam program kami. Cara kerjanya adalah pertama kali menetapkan pemboleh ubah "limpahan" menjadi sifar. Kemudian memasuki kawasan yang berlabel "sec_count" dan membandingkan limpahan dengan 30, jika tidak sama, ia kembali ke label sec_count dan membandingkan lagi, dan sekali lagi, dan lain-lain sehingga akhirnya sama (ingat bahawa sepanjang masa ini berlaku pada pengendali interupsi pemasa kami terus meningkatkan limpahan pemboleh ubah dan jadi ia berubah setiap kali kita berkeliling di sini. Apabila limpahan akhirnya sama dengan 30 ia keluar dari gelung dan kembali ke mana sahaja yang kita panggil kelewatan: dari. Hasil bersih adalah kelewatan 1/2 saat

Latihan 2: Ubah rutin overflow_handler kepada yang berikut:

over_flow_handler:

inc reti melimpah

dan jalankan program. Adakah sesuatu yang berbeza? Mengapa atau mengapa tidak?

Langkah 8: Berkelip

Akhirnya mari kita lihat rutin sekelip mata:

sekelip mata:

sbi PORTD, 4 rcall delay cbi PORTD, 4 rcall delay rjmp berkelip

Mula-mula kita menghidupkan PD4, kemudian kita memanggil subrutin penundaan kita. Kami menggunakan rcall sehingga apabila PC sampai ke pernyataan "ret" ia akan kembali ke baris berikut rcall. Kemudian kelewatan rutin penundaan selama 30 kiraan dalam pemboleh ubah limpahan seperti yang kita lihat dan ini hampir tepat 1/2 saat, kemudian kita mematikan PD4, menunda 1/2 saat lagi, dan kemudian kembali ke permulaan lagi.

Hasil bersih adalah LED berkelip!

Saya rasa anda sekarang akan bersetuju bahawa "berkedip" mungkin bukan program "hello world" terbaik dalam bahasa perhimpunan.

Latihan 3: Ubah pelbagai parameter dalam program sehingga LED berkedip pada kadar yang berbeza seperti detik atau 4 kali sesaat, dan lain-lain. Latihan 4: Ubah sehingga LED menyala dan mati untuk jangka masa yang berlainan. Contohnya hidup selama 1/4 saat dan kemudian mati selama 2 saat atau seperti itu. Latihan 5: Tukar jam TCCR0B pilih bit menjadi 100 dan kemudian terus naik ke atas meja. Pada tahap manakah ia tidak dapat dibezakan dari program "hello.asm" kami dari tutorial 1? Latihan 6 (pilihan): Sekiranya anda mempunyai pengayun kristal yang berbeza, seperti 4 MHz atau 13.5 MHz atau apa sahaja, ubah pengayun 16 MHz anda pada papan roti anda untuk yang baru dan lihat bagaimana ini mempengaruhi kadar LED yang berkelip. Anda kini harus dapat melakukan pengiraan yang tepat dan meramalkan bagaimana pengaruhnya akan mempengaruhi kadarnya.

Langkah 9: Kesimpulannya

Bagi anda yang sukar mencapai tahap ini, Tahniah!

Saya menyedari bahawa sukar untuk membanting ketika anda melakukan lebih banyak membaca dan melihat lebih tinggi daripada yang anda buat dan membuat percubaan tetapi saya harap anda telah mempelajari perkara-perkara penting berikut:

  1. Bagaimana Memori Program berfungsi
  2. Bagaimana SRAM berfungsi
  3. Cara mencari daftar
  4. Cara mencari arahan dan mengetahui apa yang mereka lakukan
  5. Cara melaksanakan gangguan
  6. Bagaimana CP melaksanakan kod, bagaimana SREG berfungsi, dan apa yang berlaku semasa gangguan
  7. Cara melakukan gelung dan melompat dan melantun di dalam kod
  8. Betapa pentingnya membaca lembaran data!
  9. Sebaik sahaja anda mengetahui bagaimana melakukan semua ini untuk mikrokontroler Atmega328p, ia akan menjadi jalan kek yang relatif untuk mempelajari pengawal baru yang anda minati.
  10. Cara mengubah waktu CPU menjadi waktu nyata dan menggunakannya dalam rutin penundaan.

Sekarang kita mempunyai banyak teori sehingga kita dapat menulis kod yang lebih baik dan mengawal perkara yang lebih rumit. Oleh itu, tutorial seterusnya yang akan kita lakukan. Kami akan membina litar yang lebih rumit, lebih menarik dan mengawalnya dengan cara yang menyeronokkan.

Latihan 7: "Hancurkan" kod dengan pelbagai cara dan lihat apa yang berlaku! Bayi ingin tahu saintifik! Orang lain boleh mencuci pinggan kan? Latihan 8: Kumpulkan kod menggunakan pilihan "-l" untuk menghasilkan fail senarai. I. E. "avra -l blink.lst blink.asm" dan lihat fail senarai. Kredit Tambahan: Kod yang tidak dikomentari yang saya berikan pada awalnya dan kod komen yang akan kita bincangkan kemudian berbeza! Terdapat satu baris kod yang berbeza. Boleh jumpa? Mengapa perbezaan itu tidak penting?

Semoga anda bergembira! Jumpa lagi lain kali …

Disyorkan: