Daftar Isi:

Bus I2C untuk ATtiny dan ATmega: 8 Langkah
Bus I2C untuk ATtiny dan ATmega: 8 Langkah

Video: Bus I2C untuk ATtiny dan ATmega: 8 Langkah

Video: Bus I2C untuk ATtiny dan ATmega: 8 Langkah
Video: I2C Bus Programming On AVR Microcontollers 2024, Juli
Anonim
Bus I2C untuk ATtiny dan ATmega
Bus I2C untuk ATtiny dan ATmega

Saya suka mikrokontroler Atmel AVR! Sejak membangun Sistem Pengembangan Ghetto yang dijelaskan dalam Instruksi ini, saya tidak pernah berhenti bereksperimen dengan AVR ATtiny2313 dan ATmega168 pada khususnya. Saya bahkan melangkah lebih jauh dengan menulis Instruksi tentang penggunaan sakelar sebagai input, dan memperluas konsep Sistem Pengembangan Ghetto ke CPLD. Selama proyek baru-baru ini, saya membutuhkan beberapa sakelar untuk menetapkan nilai kontrol. AVR tidak memiliki cukup pin I/O, jadi saya harus memikirkan sesuatu. Saya dapat mencoba sistem input yang kompleks dengan keyboard dan tampilan, tetapi ATtiny2313 akan kehabisan sumber daya. Untungnya, Atmel telah menyediakan cara untuk mengatasi masalah ini dengan menyertakan antarmuka yang dapat terhubung ke chip tambahan (seperti memori atau port I/O) dengan antarmuka dua kabel yang sederhana. Benar, hanya dengan menggunakan dua pin I/O pada AVR kita dapat mengakses banyak pin I/O tambahan, dan juga sumber daya lainnya. Antarmuka dua kabel ini secara resmi dikenal sebagai bus Inter-Integrated Circuit, atau hanya bus I2C dan ditemukan oleh NXP ketika masih menjadi Philips Semiconductors. Jika Anda membaca Instructable ini maka Anda mungkin pernah mendengar tentang bus I2C dan bahkan mungkin telah menggunakannya pada PIC atau mikrokontroler lainnya. Meskipun secara konseptual sangat sederhana, dan didukung oleh sumber daya perangkat keras pada AVR, driver perangkat lunak masih diperlukan untuk menggunakan bus I2C. Atmel menyediakan Catatan Aplikasi (lihat Sumberdaya nanti dalam Instruksi ini), tetapi ini tidak lengkap dan tidak menunjukkan contoh apa pun selain berkomunikasi dengan perangkat AVR lain. Bukan tujuan Instruksi ini untuk mengajari siapa pun cara membuat driver I2C untuk AVR. Sebaliknya, saya akan memberikan versi driver Atmel yang diperluas untuk perangkat ATtiny2313 dan ATmega168, saya akan menjelaskan persyaratan dan batasan yang berlaku saat menggunakan ini, dan saya akan menunjukkan kepada Anda contoh perangkat I2C yang berfungsi. Setelah Anda mengerjakan Instruksi ini, Anda akan dapat menggunakan bus I2C dengan sukses dalam proyek AVR Anda. Jelas, Anda dapat mengabaikan driver untuk ukuran kecil atau MEGA jika Anda hanya tertarik pada salah satunya. Bagi mereka yang tertarik untuk mempelajari lebih lanjut tentang bus I2C, saya akan memberikan tautan ke materi yang sesuai.

Langkah 1: Apa Semua Barang I2C Ini?

Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?
Apa Semua Barang I2C Ini?

Bus I2C adalah koneksi dua kabel sederhana yang dapat menghubungkan beberapa perangkat bersama-sama dan memungkinkan mereka untuk bertukar data. Dalam bentuknya yang paling sederhana ada satu perangkat master yang berkomunikasi dengan beberapa perangkat budak. Semua perangkat terhubung secara paralel ke dua kabel bus I2C. Kedua kabel tersebut dikenal sebagai SCL dan SDA. SCL adalah garis jam dan dikendalikan oleh perangkat master. SDA adalah jalur data dua arah. Untuk mentransfer data, master mengirimkan alamat slave yang dikombinasikan dengan flag baca/tulis satu bit. Jika penulisan diinginkan, master akan terus mengirim data ke slave yang dialamatkan. Jika pembacaan diminta, budak akan merespons dengan data. Untuk mengoordinasikan transaksi, jalur SCL dan SDA dimanipulasi oleh master dan slave untuk memberi sinyal beberapa kondisi. Ini termasuk START, STOP, ACK (mengakui) dan NAK (tidak mengakui). Rincian kondisi ini ditangani oleh pengemudi. Geeks sejati di antara Anda dapat mempelajari semua detail di tautan yang disediakan di akhir Instruksi ini. Persyaratan listriknya cukup sederhana. Master dan slave harus menggunakan level yang sama untuk Vcc, ground harus terhubung, dan jalur SCL dan SDA harus ditarik ke Vcc. Nilai resistor pull-up ditentukan dengan tepat oleh perhitungan berdasarkan kapasitansi total pada bus, tetapi secara praktis dapat berupa nilai antara 1,8K dan 10K. Saya mulai dengan 5.1K dan menggunakan nilai yang lebih rendah hingga berhasil. Ini biasanya tidak menjadi masalah kecuali Anda memiliki banyak perangkat atau kabel yang panjang antar perangkat. Kecepatan data nominal pada bus I2C adalah 100Kbits/detik. Tarif 400Kbits/detik, 1Mbits/detik, dan seterusnya juga dimungkinkan, tetapi tidak didukung oleh driver dalam Instruksi ini. Semua perangkat I2C akan bekerja pada 100Kbits/detik. ATtiny2313 dan ATmega168 masing-masing mengimplementasikan bus I2C secara berbeda. ATtiny2313 menggunakan perangkat keras Universal Serial Interface (USI) - yang juga dapat digunakan untuk bus SPI. ATmega168 memiliki perangkat keras khusus untuk bus I2C yang dikenal sebagai Two Wire Interface (TWI). Setelah driver ditulis, perbedaan ini sebagian besar transparan bagi pengguna. Satu perbedaan yang signifikan adalah pada perangkat lunaknya: Driver ATmega168 I2C digerakkan oleh interupsi sedangkan untuk ATtiny2313 tidak. Ini berarti bahwa program ATmega168 tidak harus menunggu transfer data I2C berlangsung, tetapi hanya perlu menunggu sebelum memulai transfer lain, atau sampai data datang dari operasi baca. Contoh-contoh dan diskusi yang harus diikuti harus memperjelas hal ini. Alamat I2C memiliki panjang 7 bit, sehingga hingga 127 perangkat dapat berada di bus jika masing-masing memiliki alamat unik. Seperti yang ditunjukkan pada gambar, alamat 7 bit ini digeser ke kiri satu bit dan bit paling tidak signifikan digunakan untuk menandai pembacaan atau penulisan perangkat di alamat tersebut. Jadi alamat budak lengkap adalah byte 8 bit. Alamat sebenarnya sebagian ditentukan secara internal ke perangkat dan tidak dapat diubah (4 bit paling signifikan), dan sebagian ditentukan oleh bit yang dapat dihubungkan ke pin perangkat (3 bit paling tidak signifikan) yang dapat diikat tinggi atau rendah untuk disetel alamat tertentu. Kedengarannya membingungkan, tetapi sebuah contoh akan memperjelas hal ini. Lembar data PCA8574A menunjukkan bahwa empat bit paling signifikan dari alamat I2C akan selalu 0111. Tiga bit berikutnya ditentukan oleh pengaturan pada pin AD0, AD1 dan AD2. Pin ini dapat diikat ke ground atau ke suplai tegangan positif (5 volt) untuk masing-masing mewakili 0 atau 1. Jadi kisaran alamat yang mungkin adalah 38 hingga 3F heksadesimal, seperti yang ditunjukkan pada gambar lain dari lembar data PCA8574. Jadi dengan mengubah pengaturan bit alamat, hingga 8 PCA8574A dapat berada di bus I2C secara bersamaan. Masing-masing akan menanggapi alamat budak spesifiknya saja. Jika lebih banyak port I/O diperlukan, PCA8574 dapat digunakan. Satu-satunya perbedaan antara PCA8574 dan PCA8574A adalah bahwa kisaran alamat slave I2C dari PCA8574 adalah 20 hingga 27 heksadesimal. Menentukan alamat perangkat tertentu dapat membingungkan karena beberapa lembar data menganggap bit baca/tulis sebagai bagian dari alamat. Baca lembar data dengan hati-hati dan ingat bahwa alamat slave akan memiliki panjang 7 bit. Bit baca/tulis harus diperlakukan secara terpisah. Sekali lagi, sebuah contoh akan membantu. Lembar data untuk EEPROM 24C16 kita akan bereksperimen dengan mengatakan empat bit pertama (paling signifikan) dari alamat slave adalah 1010. Tiga bit berikutnya dapat ditentukan oleh A0, A1 dan A2; tetapi perhatikan bahwa lembar data juga mencakup 24C01 hingga 24C08 yang merupakan EEPROM berukuran lebih kecil. Gambar dari lembar data menunjukkan bahwa pengaturan bit alamat ini diabaikan seiring bertambahnya ukuran dan sepenuhnya diabaikan untuk 24C16. Artinya, tiga bit terakhir tidak masalah dan 24C16 benar-benar menggunakan semua alamat budak I2C 50 hingga 57 heksadesimal. Kisaran alamat slave sebenarnya akan menangani bagian yang berbeda dalam 24C16. 256 byte pertama di alamat 50h, 256 berikutnya di 51h, dan seterusnya hingga 256 terakhir di 57h - dengan total 2K byte. Karena alamat RAM PCF8570 yang juga kami uji berada dalam kisaran ini, 24C16 dan PCF8570 tidak dapat digunakan bersama-sama.

Langkah 2: Pesan Beberapa Perangkat I2C

Sekarang setelah Anda mengetahui sedikit tentang Bus I2C dan ingin menggunakannya, mengapa tidak memesan beberapa perangkat I2C untuk bereksperimen sekarang sehingga mereka dapat mengantar Anda saat Anda menyiapkan perangkat lunak? Perangkat yang sesuai menyertakan I/ O Interface Expander (favorit saya), Ram Statis, dan EEPROM. Masih banyak lagi, tetapi ini adalah awal yang baik. Prosesor AVR yang akan kita gunakan adalah ATtiny2313 dan Atmega168 (digunakan di Arduino). Jika Anda baru dalam hal ini, lihat Instructable yang bagus ini untuk mempelajarinya dan membangun Sistem Pengembangan Ghetto Anda. Skema ATmega168 dalam Instructable ini menunjukkan bagaimana menerapkan Sistem Pengembangan Ghetto untuk prosesor ini. Kabel port paralel sama dengan kabel untuk ATtiny2313. (Saya belum mencoba versi USB dari Sistem Pengembangan Ghetto, jadi saya tidak yakin bagaimana bus I2C diakses di dalamnya. Sama untuk Arduino.)Berikut adalah nomor bagian Digikey. Port Expander:IC I2C I/O EXPANDER 568-4236-5-NDRam:IC SRAM 256X8 W/I2C 568-1071-5-NDEEPROM:IC EEPROM SERIAL 16K CAT24C16LI-G-ND

Langkah 3: Driver I2C

Berikut adalah deskripsi fungsi driver untuk bus I2C. Ini dikembangkan menggunakan Atmel Apps Notes sebagai permulaan. Saya tidak bisa melakukan ini tanpa mereka sebagai dasar untuk membangun. Pengembangan dilakukan menggunakan WinAVR dan compiler gcc C. Pembatasan kecepatan clock dijelaskan di bawah ini untuk setiap prosesor. Karena saya tidak dapat menguji semua kemungkinan kombinasi rasa/kecepatan jam prosesor, saya hanya akan berpegang pada apa yang sebenarnya dapat saya uji dan mencoba menunjukkan batasan dan batasannya. Berikut adalah fungsi driver dan cara menggunakannya. Silakan lihat contoh untuk detail lebih lanjut dan untuk melihat fungsi yang digunakan dalam program lengkap. Untuk ATtiny2313:Persyaratan Jam:Driver dirancang untuk kecepatan clock 1MHz (tingkat default) untuk ATtiny2313. Jika Anda ingin menjalankan pada kecepatan lain, maka Anda harus menyesuaikan konstanta di driver. Email saya jika Anda memerlukan bantuan melakukan ini. Anda juga bisa mendapatkan beberapa petunjuk dari catatan aplikasi Atmel di tautan di Langkah Sumber Daya. USI_TWI_Master_Initialise()Fungsi ini menginisialisasi perangkat keras USI untuk operasi mode I2C. Panggil sekali di awal program Anda. Ini mengembalikan batal dan tidak ada argumen. USI_TWI_Get_State_Info()Fungsi ini mengembalikan informasi kesalahan I2C dan digunakan jika kesalahan terjadi selama transaksi I2C. Karena fungsi ini hanya mengembalikan kode kesalahan, saya menggunakan fungsi TWI_Act_On_Failure_In_Last_Transmission(TWIerrorMsg) untuk mem-flash LED kesalahan. Kode kesalahan didefinisikan dalam USI_TWI_Master.h. Berikut cara memanggilnya:TWI_Act_On_Failure_In_Last_Transmission(USI_TWI_Get_State_Info())USI_TWI_Start_Read_Write()Fungsi ini digunakan untuk membaca dan menulis byte tunggal ke perangkat I2C. Hal ini juga digunakan untuk menulis beberapa byte. Ada 6 langkah untuk menggunakan fungsi ini.1)Deklarasikan buffer pesan dalam program Anda untuk menampung alamat slave dan byte data yang akan dikirim atau diterima. unsigned char messageBuf (MESSAGEBUF_SIZE);2)Masukkan Alamat Slave sebagai byte pertama dalam buffer. Geser sedikit ke kiri dan OR di bit Baca/Tulis. Perhatikan bit Baca/Tulis akan menjadi 1 untuk Baca dan 0 untuk Tulis. Contoh ini untuk Read. messageBuf(0) = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (BENAR<<TWI_READ_BIT); 3)Saat melakukan Write, letakkan byte yang akan ditulis ke lokasi berikutnya di buffer.4)Panggil fungsi USI_TWI_Start_Read_Write dengan buffer pesan dan ukuran pesan sebagai argument.temp = USI_TWI_Start_Read_Write(messageBuf, 2);5)The nilai yang dikembalikan (temp dalam hal ini) dapat diuji untuk melihat apakah terjadi kesalahan. Jika demikian, itu ditangani seperti yang dibahas di atas. Lihat contoh di program.6)Jika Baca diminta, pembacaan byte akan berada di lokasi kedua dalam buffer. Jika beberapa byte akan ditulis (seperti ke perangkat memori), rutinitas yang sama ini dapat digunakan. Menyiapkan buffer dan memanggil rutin sedikit berbeda. Byte kedua dalam buffer akan menjadi alamat memori awal untuk menulis. Data yang akan ditulis akan dalam byte berikutnya. Ukuran pesan akan menjadi ukuran termasuk semua data yang valid. Jadi jika 6 byte akan ditulis, maka ukuran pesan akan menjadi 8 (alamat slave + alamat memori + 6 byte data). USI_TWI_Start_Random_Read()Fungsi ini digunakan untuk membaca beberapa byte dari perangkat I2C, biasanya hanya berarti untuk semacam memori. Menggunakan rutin ini sangat mirip dengan rutin sebelumnya, dengan dua pengecualian. Pengaturan bit Baca/Tulis tidak masalah. Memanggil rutin ini akan selalu menyebabkan operasi Baca. Ukuran pesan harus 2 ditambah jumlah byte yang akan dibaca. Jika tidak terjadi kesalahan, data akan berada di buffer mulai dari lokasi kedua. Untuk ATmega168: Persyaratan Jam: driver dirancang untuk kecepatan clock 4MHz untuk ATmega168. Kode contoh menunjukkan cara mengatur kecepatan jam ini. Jika Anda ingin menjalankan pada kecepatan lain, maka Anda harus menyesuaikan konstanta di driver. Email saya jika Anda perlu melakukan ini. TWI_Master_Initialise()Fungsi ini menginisialisasi perangkat keras TWI untuk operasi mode I2C. Panggil sekali di awal program Anda. Ini mengembalikan batal dan tidak ada argumen. Pastikan untuk mengaktifkan interupsi dengan memanggil swi() setelah inisialisasi. TWI_Get_State_Info()Fungsi ini mengembalikan informasi kesalahan I2C dan digunakan jika kesalahan terjadi selama transaksi I2C. Karena fungsi ini hanya mengembalikan kode kesalahan, saya menggunakan fungsi TWI_Act_On_Failure_In_Last_Transmission(TWIerrorMsg) untuk mem-flash LED kesalahan. Kode kesalahan didefinisikan dalam TWI_Master.h, tetapi dimodifikasi untuk memberi sinyal pada LED kesalahan. Lihat kode contoh untuk detailnya. Berikut cara memanggilnya:TWI_Act_On_Failure_In_Last_Transmission(TWI_Get_State_Info())Perhatikan bahwa pemeriksaan kesalahan dilakukan dengan memastikan bahwa transaksi I2C selesai (fungsi yang dijelaskan di bawah) dan kemudian menguji sedikit dalam kata status global. TWI_Start_Read_Write()TWI_Start_Random_Read()Ini dua fungsi bekerja sama dengan fungsi terkait yang dijelaskan di atas tetapi dengan beberapa pengecualian. Mereka tidak mengembalikan nilai kesalahan apa pun. Data yang dibaca tidak ditransfer ke buffer. Melakukan hal ini akan dilakukan dengan fungsi yang dijelaskan selanjutnya. Saat memanggil TWI_Start_Random_Read, ukuran pesan harus berupa jumlah byte data yang diminta ditambah satu, bukan dua. Driver I2C untuk ATmega168 digerakkan oleh interupsi. Artinya, transaksi I2C dimulai dan kemudian dieksekusi secara independen sementara rutinitas utama terus berjalan. Ketika rutinitas utama menginginkan data dari transaksi I2C yang dimulai, ia harus memeriksa untuk melihat apakah data tersedia. Situasinya sama untuk pemeriksaan kesalahan. Rutin utama harus memastikan bahwa transaksi I2C selesai sebelum memeriksa kesalahan. Dua fungsi berikutnya digunakan untuk tujuan ini. TWI_Transceiver_Busy()Panggil fungsi ini untuk melihat apakah transaksi I2C selesai sebelum memeriksa kesalahan. Contoh program menunjukkan cara menggunakan this. TWI_Read_Data_From_Buffer()Panggil fungsi ini untuk mentransfer data dari buffer penerima driver I2C ke buffer pesan. Fungsi ini akan memastikan transaksi I2C selesai sebelum mentransfer data. Sementara nilai dikembalikan oleh fungsi ini, saya menemukan memeriksa bit kesalahan secara langsung lebih dapat diandalkan. Berikut cara menyebutnya. Ukuran pesan harus satu lebih besar dari jumlah bit data yang diinginkan. Data akan berada di messageBuf mulai dari lokasi kedua.temp = TWI_Read_Data_From_Buffer(messageBuf, messageSize);

Langkah 4: Mari Membangun

Mari Membangun!
Mari Membangun!
Mari Membangun!
Mari Membangun!
Mari Membangun!
Mari Membangun!
Mari Membangun!
Mari Membangun!

Mulailah dengan mengunduh file I2C Schematics.zip. Anda mungkin ingin membuat folder I2C di area kerja Anda untuk menyimpan skema dan contoh file program. Buka zip skema ke dalam direktori ini. Anda akan menemukan folder bernama I2C Schematics. Buka file bernama tiny I2C.pdf. Skema ini menunjukkan Sistem Pengembangan Ghetto ATtiny2313, dan PCA8574A I/O Port Expander (memiliki kotak putus-putus besar di sekelilingnya). Sirkuit Port Expander dibangun di atas papan tempat memotong roti. Lihat foto untuk melihat seperti apa sirkuit ini. Mereka benar-benar sangat sederhana. Bagian ATtiny2313 dari skema hanyalah Sistem Pengembangan Ghetto dengan tiga lampu kedip (LED1, 2, dan 3, plus R4, 5, dan 6) dan tombol tekan (S1) yang terhubung ke sana, ditambah satu detail tambahan. Detail itu adalah penambahan jumper (JP4, 5, dan 6) yang dapat dilepas untuk memungkinkan koneksi jalur SCL dan SDA bus I2C. Jumper harus di tempat untuk pemrograman, kemudian dilepas agar SCL dan SDA dapat terhubung. Foto-foto menunjukkan jumper di tempat dan dilepas. Penempatan jumper ini terserah Anda, Anda hanya perlu meletakkannya di Ghetto Development System Anda jika ingin menggunakan bus I2C. Bus I2C harus diputuskan dan jumper dipasang untuk pemrograman. Perhatikan bahwa Anda hanya benar-benar perlu memperhatikan JP4 dan JP6 untuk bus I2C. Masukkan JP5 jika Anda ingin menggunakan bus SPI. Breadboarding PCA8574A I/O Port Expander sangat sederhana. Menyediakan koneksi Vcc (+5 volt) dan Gnd (ground) dan menghubungkan AD0, 1, dan 2 ke ground (membuat alamat slave I2C menjadi 38 hex). Kemudian sambungkan 4 lampu kedip, dan 4 sakelar DIP. (Jika Anda tidak memiliki sakelar DIP, Anda dapat menggunakan kabel saja. Ikat ke ground atau biarkan mengambang untuk mengaktifkan atau menonaktifkan sinyal.) Terakhir, sambungkan resistor pull-up (R11 dan 12) dari SDA dan SCL ke Vcc. Ini ditampilkan sebagai 3.3K, tetapi nilai apa pun dari 1.8K hingga 5.1K akan berfungsi (mungkin hingga 10K tetapi saya belum mencobanya). Setelah Anda memprogram ATtiny2313, Anda dapat menghapus jumper dan menghubungkan SDA dan SCL untuk pengujian. Sekarang untuk ATmega168. Satu-satunya masalah di sini adalah Anda mungkin belum membangun Sistem Pengembangan Ghetto untuk prosesor ini. Jika demikian, maka skema yang saya berikan (MEGA I2C.pdf) akan menunjukkan caranya. Ini hanya permutasi dari versi ATtiny2313. Jika Anda merencanakan ke depan, Anda dapat memastikan kabel pemrograman Anda sesuai dengan kedua sistem. Perbedaan utama adalah penambahan C2 dan C3. Lihat gambar untuk penempatan ini, mereka harus sangat dekat dengan chip; salah satunya sebenarnya di bawah chip. Ini membantu menjaga kebisingan dari konverter analog ke digital pada khususnya. Anda tidak perlu memasang jumper kecuali Anda berencana menggunakan bus SPI karena tidak diperlukan untuk bus I2C pada chip ini. Perhatikan bahwa papan tempat memotong roti PCA8754A tidak akan berubah. Anda hanya akan menghubungkan SDA dan SCL dan pergilah! Mudah, ya?

Langkah 5: Mari Kode dan Uji

Mari Kode dan Uji!
Mari Kode dan Uji!
Mari Kode dan Uji!
Mari Kode dan Uji!
Mari Kode dan Uji!
Mari Kode dan Uji!

Saatnya membangun driver dan program contoh. Kita akan mulai dengan ATtiny2313 dan papan tempat memotong roti PCA8574A yang baru saja kita buat. Unduh file I2C.zip ke direktori kerja I2C Anda dan unzip. Anda akan memiliki folder baru bernama I2C. Di dalamnya Anda akan menemukan USI I2C (untuk ATtiny2313) dan TWI I2C (untuk ATmega168). Di USI I2C, Anda akan menemukan folder I_O Port. Folder itu berisi kode untuk program contoh pertama kami, dan driver USI I2C. Menggunakan WinAVR, kompilasi dan muat kode ke dalam file ATtiny2313. Ambil napas dalam-dalam dan nyalakan daya. Inilah yang diharapkan: Saat dihidupkan, LED 1 pada port PD6 dari ATtiny2313 berkedip dua kali. Tidak ada lagi yang akan terjadi sampai Anda menekan tombol (S1). Setiap kali tombol ditekan, sakelar dibaca dan pengaturannya akan ditampilkan pada LED yang terhubung ke PCA8574A. Ubah nilai sakelar, tekan tombol, dan LED akan berubah. Terus lakukan ini sampai Anda mengatasi sensasi melihatnya bekerja. Jika (Tuhan melarang!) hal-hal tidak bekerja seperti yang diharapkan, hati-hati memeriksa kabel Anda. Kesalahan I2C akan ditandai dengan kedipan pada LED3 (PD4) dan mungkin berarti Anda perlu memeriksa apakah SDA dan SCL terhubung ke pin yang benar dan ditarik dengan benar. Jika masih tidak berhasil, baca sisa bagian ini untuk mempelajari tentang debugging. Sekarang kembali dan mari kita lihat kodenya. Buka file USI_I2C_Port.c. Ini adalah kode untuk contoh program. (USI_TWI_Master.c dan USI_TWI_Master.h berisi driver - Anda dapat mengabaikannya kecuali Anda penasaran.) Gunakan contoh untuk memandu aplikasi I2C Anda sendiri. Sebagian besar, program menunjukkan kepada Anda cara menginisialisasi dan menggunakan driver I2C, termasuk pengaturan up alamat budak dan sisa buffer pesan, dan mendapatkan data dari itu. Anda juga akan melihat bagaimana saya mendebounce tombol dan mengatur loop while. Ada beberapa detail program yang layak disebutkan. Perhatikan bahwa data dari sakelar dibalik sebelum ditulis ke LED pada Port Expander. Perhatikan juga bahwa port input pada Port Expander harus ditulis sebagai High agar berfungsi dengan baik. Rincian tersebut dijelaskan dalam lembar data PCA8574A. Selalu baca lembar data dengan cermat! Yang lebih menarik adalah penggunaan debugging bersyarat. Di dekat awal file program terdapat pernyataan //#define DEBUG dan di seluruh kode terdapat pernyataan #ifdef DEBUG. Selama DEBUG tidak didefinisikan (dua garis miring membuat baris menjadi komentar dan mencegahnya didefinisikan), kode di dalam pernyataan #ifdef ke #endif tidak akan dikompilasi. Tetapi jika hal-hal tidak bekerja seperti yang Anda harapkan, kompilasi ulang dan muat ulang kode dengan #define DEBUG tanpa komentar. Anda akan mendapatkan lebih banyak kedipan pada LED yang dapat Anda dekode untuk mengikuti eksekusi program Anda dan membantu Anda menemukan dengan tepat di mana ada kesalahan. Bahkan, saya sarankan Anda mencoba ini hanya untuk melihat apa yang terjadi. Apa yang akan Anda lihat adalah bahwa LED 2 (pada PD5) akan berkedip saat eksekusi berlangsung melalui program. Nilai yang dibaca dari sakelar akan berkedip pada LED 1 (PD6) sebelum ditampilkan pada LED Port Expander. Anda seharusnya dapat melacak program saat dijalankan dengan menggunakan LED ini. Selanjutnya kita akan bekerja dengan ATmega168; lewati bagian ini jika Anda hanya tertarik dengan ATtiny2313. Masih bersamaku? Bagus. Pindah ke folder TWI_I2C, ubah direktori kerja Anda ke IO_Port, dan kompilasi dan muat TWI_I2C_Port.c ke dalam ATmega168. Putuskan sambungan jalur SDA dan SCL dari ATtiny2313 dan sambungkan ke ATmega168. Hubungkan power dan ground, dan power up. Operasinya harus sama! Mainkan sampai sensasinya mereda, lalu mari kita lihat kodenya. Buka TWI_I2C_Port.c. Kode ini hampir identik kecuali untuk penanganan kesalahan dan mengakomodasi driver yang digerakkan oleh interupsi. Berikut perbedaannya: Perhatikan bahwa jam harus disetel ke 4MHz agar bus I2C berfungsi dengan baik. sei(); pernyataan menyalakan interupsi setelah inisialisasi driver I2C. Untuk memeriksa kesalahan, bit status tertentu diuji. Selama pembacaan, fungsi TWI_Read_Data_From_Buffer harus dipanggil untuk mentransfer data yang dibaca ke buffer pesan. Selama penulisan, while (TWI_Transceiver_Busy()) harus digunakan untuk memastikan transfer selesai sebelum memeriksa kesalahan. Dua fungsi terakhir ini dijelaskan di atas dalam deskripsi driver. Selain itu, kodenya hampir sama dengan ATtiny2313. DEBUG bekerja sama juga jika Anda ingin bereksperimen dengan itu.

Langkah 6: Menggunakan Memori I2C

Menggunakan Memori I2C
Menggunakan Memori I2C
Menggunakan Memori I2C
Menggunakan Memori I2C
Menggunakan Memori I2C
Menggunakan Memori I2C
Menggunakan Memori I2C
Menggunakan Memori I2C

Sekarang kita telah belajar menggunakan bus I2C untuk membaca dan menulis I/O Port Expander, mari beralih menggunakan memori I2C, baik RAM maupun EEPROM. Perbedaan utama adalah bahwa beberapa byte dapat dibaca atau ditulis dari memori dengan satu perintah I2C. Untuk bersiap-siap untuk eksperimen ini, kita perlu sedikit memodifikasi perangkat keras dan membangun beberapa sirkuit baru di papan tempat memotong roti. Pertahankan rangkaian Port Expander karena kita akan menggunakannya untuk menampilkan beberapa nilai memori. Lepaskan sakelar DIP dari PCA8574A dan pasang lampu kedip pada pin tersebut. Jika Anda tidak memiliki cukup lampu kedip, pindahkan yang ada di P4 hingga P7 ke P0 hingga P3. (Nilai yang akan ditampilkan cukup kecil.) Sekarang lihat skema Ram.pdf I2C dan hubungkan PCF8570 pada papan tempat memotong roti. Lihat juga gambarnya. Pastikan untuk mengikat pin 7 ke Vcc. Jalankan kabel untuk SDA dan SCL dari PCA8574A. Tidak diperlukan resistor pull-up tambahan. Jika Anda juga tertarik dengan EEPROM, buat sirkuit itu juga menggunakan I2C EEPROM.pdf untuk 24C16, tetapi berhati-hatilah bahwa contoh menggunakan ATmega168. Sirkuit ini sangat sederhana. Seperti dibahas di atas, bit alamat harus diabaikan. Cukup sambungkan daya dan ground. Jangan hubungkan SDA dan SCL dulu karena kita belum selesai bereksperimen dengan Ram. Kita akan memulai eksperimen memori kita dengan ATtiny2313 yang terhubung ke Port Expander PCA8574A dan Ram PCF8570. Program akan menulis beberapa angka ke Ram, kemudian membacanya kembali dan menampilkannya di Port Expander. Ubah direktori kerja Anda ke RAM di bawah USI I2C. Gunakan file make untuk mengkompilasi dan mengunduh USI_I2C_RAM.c. Perhatikan bahwa file driver I2C identik dengan yang kami gunakan sebelumnya. Hubungkan daya dan Anda akan melihat satu kedipan pada LED 1 (PD6). Data akan ditulis ke 4 byte pertama memori. Tekan tombol dan dua byte akan dibaca kembali dan ditampilkan. Anda akan melihat satu lampu LED pada Port Expander (P0), jeda dua detik, lalu dua lampu LED (P0 dan P1). Jeda dua detik lagi dan LED akan mati. Tekan tombol lagi untuk memulai urutan lagi. Debugging mirip dengan metode yang dijelaskan di atas. Mari kita lihat kodenya. Buka USI_I2C_RAM.c. Seharusnya terlihat sangat mirip dengan kode sebelumnya. Perbedaan utama adalah rincian memori membaca dan menulis. Lihatlah cara buffer pesan dimuat sebelum panggilan yang benar-benar menulis. Byte pertama adalah alamat slave dengan bit baca/tulis diatur dengan tepat. Tetapi byte berikutnya adalah alamat memori untuk mulai menulis data. Kemudian muncul byte data aktual yang akan dimuat secara berurutan ke dalam memori mulai dari alamat yang kami tentukan. Kami menentukan ukuran pesan sebagai 6. Jadi kami mulai menulis di alamat 00 dan menulis nilai 01, 03, 02 dan 06 ke lokasi memori 00 hingga 03. Untuk membaca kembali data dari memori, kita harus menggunakan fungsi USI_TWI_Start_Random_Read. Buffer pesan mendapatkan alamat budak di byte pertama dan alamat awal di byte kedua. Kemudian panggil fungsi dengan ukuran pesan yang disetel ke jumlah byte yang akan dibaca plus 2. Perhatikan bahwa bit baca/tulis tidak masalah karena pembacaan akan tetap dilakukan. Data yang dikembalikan akan dimulai di lokasi kedua dalam buffer pesan. Setelah data dibaca, data dibalik untuk ditampilkan pada Port Expander dan ditulis satu byte pada satu waktu dengan jeda di antara nilai. Terakhir, LED Port Expander dimatikan. Penulisan ke Port Expander identik dengan apa yang dilakukan pada contoh sebelumnya. Untuk bersenang-senang, Anda dapat menghapus komentar pernyataan #define DEBUG seperti di atas dan melihat banyak LED berkedip. Dibanjiri kegembiraan setelah eksperimen sukses lainnya, mari beralih ke ATmega168 dan EEPROM. Ubah direktori kerja Anda ke EEPROM di bawah TWI I2C. Gunakan file make untuk mengkompilasi dan mengunduh TWI_I2C_EEPROM.c. Perhatikan bahwa file driver I2C identik dengan yang kami gunakan sebelumnya untuk PCA8574A. Untuk menguji program, lepaskan ATtiny2313 dan hubungkan ATmega168. Biarkan bus I2C terhubung ke Ram dan nyalakan. Hasilnya berbeda karena kami sekarang menulis dan membaca lebih banyak data. LED 1 pada PD7 harus berkedip saat inisialisasi. Tekan tombol dan data akan dibaca kembali dari memori dan ditampilkan. LED pada PCA8574 harus berkedip dengan urutan berikut: P1, P0 & P2, (mati semua), P0 & P1, P1 & P2. Akhirnya LED Port semua harus mati. Tekan tombol lagi untuk mengulangi ini. Oh, tapi tunggu, katamu. Bukankah program ini untuk EEPROM? Karena kita mengakses perangkat memori pada alamat I2C yang sama, program yang sama bekerja untuk Ram dan EEPROM. Matikan dan pindahkan SDA dan SCL dari Ram ke EEPROM dan jalankan program lagi. Ini harus bekerja persis sama. Perhatikan bahwa EEPROM dan Ram tidak dapat dihubungkan ke bus I2C secara bersamaan karena mereka berbagi alamat yang sama. (Yang pintar di antara Anda mungkin mempertimbangkan untuk mengubah bit alamat yang dapat diprogram pada Ram, tetapi itu tetap tidak akan berhasil. 24C16 menggunakan seluruh blok alamat yang dapat diprogram untuk Ram.) Oke, mari kita lihat program terakhir ini. Buka TWI_I2C_EEPROM.c. Hal pertama yang harus diperhatikan adalah bahwa saya telah menunjukkan cara mengatasi EEPROM 24C16 lengkap. Itu dapat diakses dalam potongan 256 byte di 8 alamat slave I2C yang berbeda. Lihat bagaimana MEMORY_ADDR didefinisikan sebagai alamat awal pada 50 heksadesimal; itu sebabnya Ram bekerja. Jika Anda ingin mengakses blok lain dari 24C16, gunakan alamat lain seperti yang saya tunjukkan. Lihat bagaimana saya mengatur untuk menulis ke memori. Pertama alamat slave dengan set bit baca/tulis dimasukkan ke dalam buffer, kemudian alamat awal 00, kemudian 16 byte data. Fungsi TWI_Start_Read_Write dipanggil untuk menulis data (seperti sebelumnya) dengan ukuran pesan diatur ke 18. Saat tombol ditekan, kami menggunakan TWI_Start_Random_Read dan TWI_Read_Data_From_Buffer untuk membaca data kembali. Setiap byte ketiga ditampilkan pada LED Port Expander. Akhirnya, LED dimatikan untuk menunggu penekanan tombol berikutnya. Anda mungkin bertanya-tanya mengapa saya memilih untuk menulis 16 byte. Jika Anda membaca lembar data dengan cermat, Anda akan melihat bahwa 24C16 melakukan siklus tulis setiap kali menerima 16 byte bahkan jika lebih banyak byte yang dikirim. Jadi itu sepertinya nomor yang bagus untuk digunakan. Jika Anda memilih untuk meningkatkan ini, Anda harus mengubah ukuran MESSAGEBUF_SIZE. Anda juga harus mengubah nilai TWI_BUFFER_SIZE di TWI_Master.h. Ini karena driver menyalin data dari buffer pesan untuk digunakan oleh rutin layanan interupsi. Selamat! Anda sekarang siap menggunakan bus I2C dalam proyek Anda sendiri!

Langkah 7: Sumber Daya Web

Berikut adalah tautan ke lembar data untuk bagian yang digunakan untuk percobaan. Anda pasti harus mendapatkan ini jika Anda tidak mendapatkan yang lain. Port ExpanderRamEEPROMSebagai pencipta I2C, NXP (Philips) memiliki banyak hal hebat. (Mereka suka menggunakan tanda kurung siku di URL mereka, jadi saya tidak dapat memasukkannya dengan benar di sini. Maaf.] Untuk masuk ke area I2C, pilih Antarmuka dari daftar Produk. Anda akan dapat membuka situs I2C mereka dan akses ke semua lembar data dan catatan aplikasi yang mereka tawarkan. Deskripsi bus I2C dan detail teknis khususnya ada di sini. Dapatkan lembar data ATtiny2313 dan ATmega168 (buku data?) dari Atmel. Catatan aplikasi Atmel ada di sini. Lihat AVR310 dan AVR315. Ambil kodenya juga. Lihat di sini untuk lebih banyak barang I2C.

Langkah 8: Catatan untuk Geeks

Untuk geek sejati yang ingin mengetahui detailnya, berikut adalah beberapa hal yang perlu diingat jika Anda melihat Catatan Aplikasi Atmel dan kode driver: - Metode pengalamatan dan perintah perangkat I2C bukan bagian dari spesifikasi! Selain alamat slave dan bit baca/tulis, perintah, mode, dll. tidak ditentukan dan khusus untuk perangkat tertentu. Untuk memperjelas ini, perhatikan bahwa skema yang digunakan dalam contoh Atmel hanya berlaku untuk contoh itu, dan cukup banyak non-standar.- Implementasi USI berbeda dari implementasi TWI dalam beberapa hal penting. + Dengan USI, pencatatan jam kerja disediakan oleh perangkat lunak; dengan TWI disediakan oleh Bit Rate Generator. + Metode USI tidak menggunakan interupsi; TWI melakukannya. Ini masuk akal karena keluarga Mega (menggunakan TWI) dapat melakukan banyak hal lain dan tidak boleh diganggu oleh transfer I2C. Versi yang digerakkan oleh interupsi untuk USI tentu saja mungkin, hanya saja tidak diimplementasikan dalam Instructable ini. + Perangkat keras USI tidak dioptimalkan untuk I2C dan hanya dapat menangani transfer 8 bit. Ini berarti bahwa dua transfer diperlukan untuk mengirim bit kesembilan (baik NACK atau ACK). Perangkat keras TWI menangani ini secara otomatis. Ini membuat implementasi driver USI sedikit lebih rumit. + Deteksi kesalahan untuk TWI ditangani di perangkat keras. USI memerlukan penanganan dalam perangkat lunak yang agak menyulitkan. + Perangkat keras TWI mengontrol konfigurasi port secara langsung. Perangkat keras USI mengharuskan bit port dikonfigurasi sebelum port dapat digunakan. Anda akan melihat ini dalam rutinitas Master_Initialize untuk USI.- Atmel mengklaim mungkin untuk menggunakan pull-up port AVR untuk pull-up bus I2C. Saya belum menemukan cara untuk membuat pendekatan itu berhasil. Menggunakan dua resistor eksternal sepertinya skema yang cukup sederhana, jadi saya tidak menghabiskan banyak waktu untuk ini.

Direkomendasikan: