Top Banner
BAGIAN 1: I2C Bus Protokol I2C menghubungkan sensor, RTC, EEPROM, dan lain-lain. I2C berkomunikasi didasari oleh acknowladge. Hanya menggunakan 2 pin untuk transfer data. SCL (Serial Clock) berfungsi untuk menyelaraskan transfer data diantara 2 chip dan SDA (Serial Data). Karakteristik Elektrik Jalur I2C Peralatan I2C hanya menggunakan 2 jalur dan 2 jalur tersebut masing-masing mempunyai 2 arah (bidirectional open-drain) untuk komunikasi data. Untuk mengimplementasikan I2C hanya menggunakan sebuah resistor pull-up 4k7 untuk setiap jalur bus. Ini mengimplementasikan sebuah jalur AND yang mana jika satu atau lebih device mengirim data zero(0) level, maka keadaan jalur menjadi zero(0) pula dan keadaan jalur akan bernilai 1 jika tidak ada satupun device mengirimkan level zero (0). I2C Node Pada AVR, I2C dapat menampung sampai 120 device yang berbeda. Setiap device disebut node. Pada istilah I2C, setiap node dapat beroperasi sebagai master atau slave. Master adalah peralatan yang menghasilkan clock untuk sistem. Master juga yang akan menandakan ataupun mengakhiri sebuah transmisi data. Slave adalah node yang menerima clock dan slave diberikan sebah alamat oleh master. Di dalam I2C, baik master atau slave dapat menerima atau mengirim data, jadi ada 4 mode operasi. Yaitu: master sebagai transmitter (pengirim), master sebagai receiver (penerima), slave sebagai transmitter (pengirim), slave sebagai receiver (penerima). Hal | 1
48

I2C bus protocol

Aug 07, 2015

Download

Documents

I2C bus protocol
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: I2C bus protocol

BAGIAN 1: I2C Bus Protokol

I2C menghubungkan sensor, RTC, EEPROM, dan lain-lain. I2C berkomunikasi didasari oleh acknowladge. Hanya menggunakan 2 pin untuk transfer data. SCL (Serial Clock) berfungsi untuk menyelaraskan transfer data diantara 2 chip dan SDA (Serial Data).

Karakteristik Elektrik Jalur I2C

Peralatan I2C hanya menggunakan 2 jalur dan 2 jalur tersebut masing-masing mempunyai 2 arah (bidirectional open-drain) untuk komunikasi data. Untuk mengimplementasikan I2C hanya menggunakan sebuah resistor pull-up 4k7 untuk setiap jalur bus. Ini mengimplementasikan sebuah jalur AND yang mana jika satu atau lebih device mengirim data zero(0) level, maka keadaan jalur menjadi zero(0) pula dan keadaan jalur akan bernilai 1 jika tidak ada satupun device mengirimkan level zero (0).

I2C Node

Pada AVR, I2C dapat menampung sampai 120 device yang berbeda. Setiap device disebut node. Pada istilah I2C, setiap node dapat beroperasi sebagai master atau slave.

Master adalah peralatan yang menghasilkan clock untuk sistem. Master juga yang akan menandakan ataupun mengakhiri sebuah transmisi data.

Slave adalah node yang menerima clock dan slave diberikan sebah alamat oleh master.

Di dalam I2C, baik master atau slave dapat menerima atau mengirim data, jadi ada 4 mode operasi. Yaitu: master sebagai transmitter (pengirim), master sebagai receiver (penerima), slave sebagai transmitter (pengirim), slave sebagai receiver (penerima).

Gambar 1. I2C Bus

CATATAN: setiap node bisa mempunyai lebih dari 1 mode operasi pada waktu berbeda, tetapi node juga hanya mempunyai 1 mode operasi pada satu waktu.

Hal | 1

Page 2: I2C bus protocol

Contoh:

Berilah sebuah contoh untuk menunjukkan bagaimana sebuah device (mode) dapat mempunyai lebih dari 1 mode operasi.

Solusi:

Jika kamu menghubungkan sebuah IC AVR ke sebuah EEPROM dengan I2C, maka AVR menjadi master yang mengirim/menulis data ke EEPROM. AVR juga menjadi master yang menerima data dengan cara membaca data dari EEPROM. Pada penjelasan selanjutnya kita akan melihat bahwa sebuah node dapat berlaku sebagai pengirim dan penerima pada waktu yang berbeda.

Format Bit

I2C adalah protocol serial sinkronus. Setiap bit data yang dikirim pada jalur SDA di sinkronasi oleh sebuah pulsa High to Low dari clock pada jalur SCL. Berkenaan dengan protocol I2C, jalur data tidak dapat berubah ketika jalur clock tinggi. Jalur data dapat berubah hanya jika ketika jalur clock rendah. Iihatlah gambar di bawah.

Gambar 2. I2C Bit Format

Kondisi START dan STOP

Sebagaimana telah kita sebutkan sebelumnya, I2C adalah sebuah hubungan / komunikasi yang berorientasi pada protocol. Ini berarti bahwa setiap transmisi dimulai oleh kondisi START dan diakhiri oleh STOP. Ingat bahwa 2 kondisi ini dibuat oleh master. Kondisi START dan STOP harus dibedakan dari bit alamat atau data. Itulah kenapa START dan STOP tidak mematuhi peraturan bit format yang kita sebutkan sebelumnya (lihat sub format bit diatas).

Kondisi START dan STOP dibuat dengan menjaga level dari jalur SCL sebagai High dan kemudian merubah level dari jalur SDA.

Kondisi START dibuat oleh perubahan High ke Low pada SDA ketika SCL High.

Kondisi STOP dibuat oleh perubahan Low ke High pada SDA ketika SCL High.

Hal | 2

Page 3: I2C bus protocol

Gambar 3. Kondisi START dan STOP

Bus benar-benar dalam keadaan sibuk diantara setiap sepasang dari kondisi START dan STOP dan tidak ada master lain yang mencoba untuk mengambil kontrol dari bus ketika jalur bus ini sibuk. Jika sebuah master yang mana mempunyai kontrol dari bus, berharap untuk mengajukan transfer baru, master memberikan sebuah kondisi START baru diantara sebuah sepasang kondisi START dan STOP. Ini disebut REPEATED START.

Gambar 4. Kondisi REPEATED START

Contoh

Berilah sebuah contoh untuk menunjukkan ketika sebuah master harus menggunakan kondisi REPEATED START. Apa yang akan terjadi jika master tidak menggunakan REPEATED START?

Solusi:

Jika kamu menghubungkan 2 buah AVR (AVR A dan AVR B) dan sebuah EEPROM dengan I2C, dan AVR A ingin menampilkan penambahan dari isi alamat 0x34 dan 0x35 dari EEPROM AVR A harus menggunakan kondisi REPEATED START.

Mari kita lihat apa yang akan terjadi jika AVR A tidak menggunakan kondisi REPEATED START.

AVR A mengirim sebuah kondisi START, kemudian membaca isi dari alamat 0x34 dari EEPROM ke dalam R16, dan mengirim sebuah kondisi STOP untuk meninggalkan bus. Sebelum AVR A membaca isi dari alamat 0x35 kedalam R17. AVR B merampas bus tersebut dan merubah isi dari alamat 0x34 dan 0x35 dari EEPROM. Kemudian AVR A membaca isi dari alamat 0x35 kedalam R17, menambahkan R17 ke R16 dan menampilkan hasilnya di LCD. Hasil pada LCD bukanlah hasil penjumlahan dari nilai yang lama

Hal | 3

Page 4: I2C bus protocol

dari alamat 0x34 dan 0x35 akan tetapi jumlah dari nilai yang baru dari alamat 0x34 dan 0x35 dari EEPROM.

Format paket di I2C

Pada I2C, setiap alamat atau data yang akan dikirim harus dibingkain ke dalam sebuah paket. Setiap paket panjangnya 9 bit.

8 bit pertama dimasukan kedalam jalur SDA oleh transmitter. Dan bit ke-9 adalah sebuah acknowledge (ACK) oleh receiver atau bisa juga sebuah Not

Acknowladge(NACK). Clock dibuat oleh master, tanpa menghiraukan apakah ini adalah master transmitter atau

receiver. Untuk mendapatkan acknowaldge, transmitter melepaskan jalur SDA selama Clock ke-9

sehingga receiver dapat menarik jalur SDA menjadi Low untuk mengindikasikan sebuah ACK Jika receiver tidak menarik jalur SDA menjadi rendah (Low), maka dianggap sebagai NACK.

Lihat gambar di bawah ini.

Gambar 5. Format paket I2C

Pada I2C, setiap paket bisa berisi alamat atau data. Catat juga bahwa kondisi START + Paket Alamat + satu atau lebih paket data + kondisi STOP bersama-sama membentuk sebuah pengiriman data. Sub-bab selanjutnya kita akan mempelajari alamat dan format paket data dan bagiamana untuk menyatukan mereka semua untuk membuat sebuah pengiriman yang sempurna.

Format Paket Alamat

Seperti paket lainnya, semua paket alamat yang dikirim pada I2C bus adalah panjangnya 9-bit. Sebuah paket alamat terdiri dari 7 alamat bit, 1 buah Read/Write Kontrol bit dan 1 buah ACK-bit.

Hal | 4

Page 5: I2C bus protocol

Gambar 6. Format Paket Alamat pada I2C

Alamat bit digunakan untuk mengalamati sebuah device slave yang spesifik pada bus. 7 bit alamat memperbolehkan master mengalamati maksimum 128 slave pada bus. Meskipun alamat 0000 0000 diperuntukan untuk panggilan umum dan semua alamat dari format 1111 xxxx telah dipesan. Itu berarti 119 (128-1-8) device bisa membagikan sebuah bus I2C. Pada bus I2C, alamat MSB dikirim pertama kali.

Bit ke-8 di dalam paket adalah READ/WRITE kontrol bit. Jika bit ini diset 1 maka master akan membaca frame selanjutnya (Data) dari slave, jika diset 0, maka master akan menulis frame selanjutnya (Data) pada jalur bus kepada slave.

Ketika slave mendeteksi alamat ini (bit ke-8) pada bus, hal ini diketehui bahwa ini sedang dialamati dan ini harus berupa acknowledge pada bit ke-9 SCL (ACK) Cycle dengan merubah SDA menjadi 0. Jika pengalamatan slave belum siap atau untuk suatu alasan yang tidak diinginkan untuk melayani master, maka master harus menjadikan bit ke-9 pada clock cycle jalur SDA dalam kondisi High (1). Hal ini mengindikasikan NACK. Pada kasus NACK, master dapat mengirim sinyal kondisi STOP untuk mengakhiri pengiriman, atau kondisi REPEATED START untuk mengajukan pengiriman baru.

Contoh:

Tunjukkan bagaimana sebuah master mengatakan bahwa master ingin menulis ke slave dengan alamat 1001101.

Solusi:

Beberapa hal ini dilakukan oleh master:

1. Master akan menaruh sebuah pulsa High ke Low pada SDA ketika SCL dalam keadaan High untuk menghasilkan sebuah kondisi START bit untuk memulai pengiriman.

2. Master mengirimkan 1001101 ke dalam bus. 7 bit pertama (1001101) mengindikasikan alamat slave, dan bit ke-8 (0) mengindikasikan operasi penulisan (Write) dan mengatakan bahwa master akan menulis byte selanjutnya (data) ke dalam slave.

Hal | 5

Page 6: I2C bus protocol

Sebuah paket alamat yang terdiri atas sebuah alamat slave dan sebuah READ disebut SLA+R, sementara sebuah paket alamat yang terdiri atas sebuah alamat slave dan sebuah WRITE disebut SLA+W.

Seperti yang telah kita sebutkan sebelumnya, alamat 0000 0000 telah dipesan untuk panggilan umum. Ini berarti bahwa ketika sebuah master mengirimkan alamat 0000 0000, semua slave menanggapi dengan merubah jalur SDA menjadi 0 dan menunggu untuk menerima byte data. Hal ini sangat berguna ketika sebuah master ingin mengirim byte data yang sama ke semua slave pada sistem. Perhatikan bahwa alamat panggilan umum (0000 0000) tidak dapat digunakan untuk membaca data dari slave dikarenakan tidak ada lebih dari 1 slave yang mampu untuk menulis ke bus pada waktu yang bersamaan.

Format Paket Data

Seperti paket lainnya, paket data juga mempunyai panjang 9 bit. 8 bit pertama adalah sebuah byte data yang akan dikirim dan bit ke-9 adalah ACK. Jika si penerima telah menerima byte terakhir atau si penerima tidak dapat menerima atau memperoses data lebih lebih, maka receiver(penerima) akan memberikan sinyal NACK dengan meniggalkan jalur SDA dalam keadaan tinggi (1). Pada paket data, sama seperti paket alamat, MSB dikirim terlebih dahulu.

Menggabungkan Paket Alamat dan Data ke dalam sebuah transmisi

Pada I2C secara normal, sebuah transmisi dimulai oleh sebuah kondisi START diikuti oleh sebuah paket alamat (SLA+R/W). satu atau lebih paket data, dan diakhiri oleh sebuah kondisi STOP.

Gambar berikut menunjukan sebuah transmisi data yang umum. Untuk mengerti setiap elemen di dalam gambar. Lihat contoh di bawah gambar tersebut.

Hal | 6

Page 7: I2C bus protocol

Contoh:

Tunjukan bagaimana sebuah master menulis nilai 1111 0000 ke slave dengan alamat 1001101.

Solusi:

Beberapa aksi ini dilakukan oleh master:

1. Master akan menaruh sebuah pulsa High ke Low pada jalur SDA sementara SCL High untuk membuat sebuah kondisi START untuk memulai transmisi.

2. Master mengirimkan 1001101 ke dalam bus 7 bit pertama (1001101) mengindikasikan alamat slave dan bit ke-8 (0) mengindikasikan operasi menulis (WRITE) membuat master akan menulis byte selanjutnya (data) kedalam slave.

3. Kemudian slave akan memukul jalur SDA menjadi sinyal rendah (0) untuk mengatakan bahwa dia (slave) telah siap untuk menerima byte data.

4. Sesudah menerima ACK, Master akan mengirimkan byte data (1111 0000) pada jalur SDA (Pertama-tama MSB).

5. Ketika slave device telah selesai menerima data maka slave meninggalkan jalur SDA dalam kondisi HIGH (1) untuk membuat sebuah sinyal NACK. Hal ini memberitahukan master bahwa slave telah menerima byte data terakhir dan tidak memerlukan data lagi.

6. Sesudah menerima NACK, master akan tahu bahwa tidak ada lagi data yang harus di transmisikan. Master akan merubah jalur SDA ketika jalur SCL High(1) untuk mengirim sebuah kondisi STOP dan kemudian meniggalkan bus.

Melonggarkan Clock

Salah satu keistimewaan dari protocol I2C adalah clock stretching (pelonggaran/perpanjangan clock). Ini adalah jenis dari kontrol aliran. Jika sebuah slave yang telah dialamati tidak siap untuk memproses data lagi maka slave akan memperlonggar clock dengan menahan jalur clock (SCL) Low (rendah) sesudah menerima (atau mengirim) sebuah bit dari data. Demikian juga master tidak akan

Hal | 7

Page 8: I2C bus protocol

dapat menaikan jalur clock (karena device adalah dijalur AND-kan) dan master akan menunggu sampai slave membebaskan jalur SCL untuk menunjukkan master telah siap untuk mengirim bit selanjutnya.

Gambar 8. Pelonggaran Clock

Arbitrasi (Pewasitan)

Protokol I2C mendukung sebuah sistem bus multi-master . Ini tidak berarti bahwa lebih dari 1 master yang dapat menggunakan bus pada saat yang bersamaan. Lebih baik, setiap master menunggu transmisi yang berlangsung sampai selesai dan memulai menggunakan bus lagi. Tetapi ini dapat juga memungkinkan 2 atau lebih master mengajukan sebuah pengiriman pada waktu yang bersamaan. Pada kasus ini maka diperlukan sebuah arbitrasi (pewasitan).

Setiap pengirim (transmiter) harus memeriksa level dari bus dan membandingkan jalur bus dengan level yang diharapkan; jika levelnya tidak cocok, transmitter tersebut telah kehilangan pewasitan dan akan dirubah kedalam mode slave.

Pada kasus arbitrasi, master yang menang akan melanjutkan pekerjaannya. Catat bahwa tidak ada bus yang akan rusak ataupun data yang hilang. Lihat contoh di bawah ini:

Contoh:

Dua buah master A dan B dimulai pada waktu yang sama. Apa yang akan terjadi jika master A ingin menulis ke slave 0010 000 dan master B ingin menulis ke slave 0001 111?

Solusi:

Master A akan kehilangan pewaktuan pada clock ke-3 karena jalur SDA berbeda dari keluaran master A pada clock ke-3. Master A dirubah menjadi mode slave dan meninggalkan bus sesudah kehilangan pewasitan.

Hal | 8

Page 9: I2C bus protocol

Multibyte burst Write (Menulis Multibyte secara penuh)

Mode menulis burst adalah sebuah cara yang efektif untuk memuati sebuah lokasi secara berurutan. Burst mode banyak dipakai pada I2C, SPI dan banyak lagi serial protocol. Pada Burst mode, kita menyediakan alamat dari lokasi pertama kemudian diikuti oleh data untuk lokasi tersebut. Dari situ, byte yang berurutan ditulis ke lokasi memory yang berurutan. Pada mode ini, I2C device secara internal menaikan alamat lokasi sepanjang kondisi STOP belum dideteksi.

Step berikut digunakan untuk mengirim (menulis) multibyte data pada mode burst untuk device I2C.

1. Membuat sebuah kondisi START2. Mengirim alamat slave diikuti oleh 0 (zero) untuk menulis3. Mengirim alamat dari lokasi data pertama4. Mengirim data untuk lokasi pertama dan dari situ, secara sederhana menyediakan byte data

yang berurutan untuk ditempatkan pada memori lokasi yang berurutan.5. Membuat sebuah kondisi STOP

Gambar di bawah ini menunjukkan bagaimana menulis 0x01, 0x02 dan 0x03 ke-3 lokasi yang berurutan dimulai dari lokasi 0000 1111 dari slave 1111 000

Gambar 9. Multibyte Burst Write

Hal | 9

Page 10: I2C bus protocol

Multibyte Burst Read (Membaca Multibyte secara penuh)

Mode membaca burst adalah sebuah cara yang efektif untuk membawa keluar isi dari lokasi yang berurutan. Pada mode burst, kita menyediakan alamat dari lokasi pertama saja. Dari situ, isinya dibawa keluar dari lokasi memori yang berurutan. Pada mode ini, device I2C secara internal menaikan lokasi alamat sepanjang belum di deteksi kondisi STOP. Step berikut digunakan untuk mendapatkan (read) multibyte data menggunakan mode burst untuk device I2C.

1. Membuat sebuah kondisi START2. Mengirim alamat slave diikuti oleh 0 (zero) untuk address write3. Mengirim alamat dari lokasi pertama4. Membuat sebuah kondisi REPEATED START5. Mengirim alamat slave diikuti oleh 1 (untuk membaca)6. Baca data dari lokasi pertama dan dari situ, bawa isi keluar dari lokasi memory berurutan7. Membuat sebuah kondisi STOP

Gambar di bawah ini menunjukkan bagaimana untuk membaca 3 lokasi yang berurutan dimulai dari lokasi 0000 1111 dari nomor slave 1111 000.

Gambar 10. Multibyte Burst read

Bagian 2: TWI (I2C) pada AVR

Pada banyak aplikasi, termasuk datasheet AVR, I2C menunjukkan kepada Two Wire Serial Interface (TWI). Mulai sekarang, kita akan menggunakan istilah TWI sebagaimana pada datasheet. Pada bagian ini, kita akan membicarakan modul TWI dan registernya pada AVR. Kemudian kita tunjukkan bagaimana memprogram AVR ke alamat sebuah device slave dan mengirim atau menerima data menggunakan TWI. Modul TWI pada AVR terdiri dari 4 sub modul:

1. Unit pembuat bit rate (Bit Rate Generation Unit)2. Unit hubungan bus (Bus Unit Interface)3. Unit pencocokan alamat (Address Match Unit)4. Unit Kontrol (Control Unit)

Gambar dibawah ni menunjukkan modul TWI. Semua register yang digambar garis tebal dapat diakses melalui data bus AVR.

Hal | 10

Page 11: I2C bus protocol

Gambar 11. TWI (I2C) pada I2C

Bit rate generation Unit mengatur frekuensi dari clock sistem (SCL) ketika beroperasi pada sebuah mode master.

Bus Interface Unit mendeteksi dan membuat kondisi START, REPEATED START, START, dan STOP. Bus interface unit juga mendeteksi arbitrasi, mengatur pengiriman atau penerimaan ACK dan juga mengirim paket data atau paket alamat.

Address match Unit membandingkan byte alamat yang diterima dengan 7-bit alamat pada TWI Address Register (TWAR) dan memberitahukan Control Unit tentang sebuah kecocokan alamat.

Control Unit mengatur modul TWI dan membuat tanggapan berkenaan dengan pengaturan pada TWI Control Register (TWCR). Control Unit juga menset isi dari Status Register yang berkenaan dengan keadaan terbaru (current state).

Pada mikrokontroller AVR, 5 register besar yang berhubungan dengan TWI. Mereka adalah TWBR (TWI Bit Rate Register), TWCR(TWI Control Register), TWSR(TWI Status Register), TWAR(TWI Address Register), TWDR(TWI Data Register). Kemudian kita akan fokuskan pada register yang berkenaan dengan TWI dan mempelajari setiap bit dari mereka secara detail.

TWI Bit Rate Register (TWBR)

Gambar di bawah menunjukan register TWBR dan bitnya.

TWBR memilih faktor pembagi untuk mengatur frekuensi clock SCL pada mode master. Frekuensi SCL diatur oleh pengaturan pada TWBR dan bit Prescaler pada TWSR (TWI Status Register).

Hal | 11

Page 12: I2C bus protocol

Persamaan berikut memperlihatkan hubungan antara frekuensi SCL, TWBR, dan TWPS bit pada TWI Status Register:

Frekuensi SCL =

Catat bahwa harga TWBR harus 10 atau lebih tinggi lagi jika TWI beroperasi pada mode master. Contoh di bawah ini menunjukan bagaimana frekuensi dari SCL dihitung.

Contoh:

Hitunglah frekuensi SCL jika harga bit TWPS pada TWSR bernilai 01(1 desimal) dan harga TWBR adalah 0010 0110 (38 desimal). Asumsikan bahwa frekuensi CPU adalah 8MHz.

Solusi:

Frekuensi SCL akan: 8MHz/(16+2(38)x41) = 25 kHz

TWI Status Register (TWSR)

Sebagaimana kita lihat pada gambar 12 dibawah ini. 5 bit (TWS3…7) dari TWSR diperuntukan untuk menunjukkan status dari logika TWI dan bus TWI. Catat bahwa jika kamu membaca TWSR, kamu akan membaca keduanya (status bit dan nilai prescaler). Untuk memeriksa status bit, kamu harus menyembunyikan 2 bit LSB (prescaler bit) menjadi 0 (zero). Pada buku ini kita tidak akan mendaftarkan semua kode status dan arti setiap kode, tetapi kita akan mencakupi beberapa dari kode yang umum. Untuk melihat daftar lengkap dari kode register status, kamu harus melihat kepada datasheet. Selanjutnya kita akan melihat bagaimana menggunakan bit-bit ini ketika kita ingin memprogram AVR menggunakan modul TWI.

Gambar 12. TWSR: TWI Status Register

Hal | 12

Page 13: I2C bus protocol

TWI Control Register (TWCR)

TWCR mengatur operasi dari TWI. Pada gambar di bawah ini kamu melihat setiap bit dari TWCR dan penjelasan secara singkatnya. Disini kita akan menjelaskan beberapa bit lebih detail.

Bit 7 – TWINT: TWI Interrupt

Bit ini diset 1 oleh hardware ketika modul TWI telah menyelesaikan pekerjaannya yang baru (current job). Jika TWI dan general interrupt di enable, merubah TWINT menjadi 1 akan menyebabkan MCU meloncat ke vector interrupt TWI. Mengosongkan (0) flag ini artinya memulai operasi TWI. TWINT harus di kosongkan oleh Software .

Bit 6 – TWEA: TWI Enable Acknowladge

Menjadikan bit ini menjadi HIGH (1) akan meng-enable pembuatan ACK ketika diperlukan pada slave atau mode penerima (receiver).

Bit 5 – TWSTA: TWI START condition bit

Menjadikan bit ini menjadi HIGH (1) akan membuat kondisi START jika bus sedang kosong; sebaliknya, modul TWI menunggu bus sampai kosong dan kemudian membuat kondisi START.

Bit 4 – TWSTO: TWI STOP condition bit

Pada mode master, membuat bit ini menjadi HIGH(1) menyebabkan TWI membuat sebuah kondisi STOP. Bit ini dihapus (0) oleh hardware ketika kondisi STOP dikirimkan.

Bit 3 – TWWC: TWI Write Collision Flag

Bit ini mejadi HIGH(1) ketika kita mencoba mengakses TWI Data Register (TWDR) ketika TWINT dalam keadaan rendah(0). Flag ini dihapus(0) dengan menulis ke register TWDR ketika TWINT dalam keadaan HIGH(1).

Bit 2 - TWEN: TWI Enable

Menjadikan bit ini HIGH (1) akan meng-enable modul TWI

Bit 0 – TWIE: TWI Interrupt Enable

Menjadikan bit ini HIGH (1) akan meng-enable TWI Interrupt jika general interrupt di-enable.

Hal | 13

Page 14: I2C bus protocol

TWI Interrupt (TWINT) flag

Ketika hardware TWI selesai mengerjakan pekerjaannya, hardware TWI akan menjadikan bit TWINT menjadi satu(1). Jika TWI dan general interrupt di-enable, merubah TWINT menjadi HIGH (1) akan menyebabkan MCU meloncat ke vector interrupt TWI. Ketika bit TWINT di-set, modul TWI akan “mengulur” jalur SCL untuk menyediakan cukup waktu bagi software untuk mengerjakan pekerjaan tetapnya. Ketika software telah menyelesaikan pekerjaanya, bit TWINT harus di-clear untuk melanjutkan operasi dari modul TWI. Catat bahwa semua jalan masuk menuju TWI address, status, dan data register harus diselesaikan sebelum meng-clear bit ini. Jika kamu mencoba untuk menulis ke TWI Data Register ketika TWINT dalam keadaan low (0), sebuah bentrokan (collision) flag (TWWC) akan diset HIGH(1) oleh hardware. Software dapat menangkap (menyelidiki) bit TWI untuk mengetahui ketika modul TWI telah menyelesaikan pekerjaannya dan telah siap untuk perintah baru.

TWI Enable Acknowladge (TWEA) bit

Menjadikan bit ini HIGH (1) akan meng-enable pembuatan bit ACK jika ada beberapa kondisi ditemui:

1. Modul TWI Address Match menemukan bahwa modul TWI dialamati dengan menerima alamat slave dirinya sendiri dari bus.

2. Sebuah general call telah selesai diterima sementara bit TWGCE pada TWAR di-set menjadi satu(1) untuk memperbolehkan penerimaan panggilan global.

3. Sebuah data byte telah selesai diterima pada setiap mode penerimaan, mode master penerima atau slave penerima.

Jika kamu meng-clear bit TWEA menjadi 0(zero), device tidak akan membuat ACK dan akan secara virtual diputus dari bus TWI.

TWI Start bit dan TWI Stop bit (TWSTA dan TWSTO)

Untuk membuat kondisi START dan STOP, kamu harus men-set bit TWSTA atau TWSTO menjadi satu(1) berturut-turut dan kemudian meng-clear TWINT flag menjadi zero (0) dengan menuliskan satu(1) ke flag TWINT tersebut.

TWI Data Register (TWDR)

Pada mode penerima, byte terakhir yang diterima akan berada pada TWDR, dan pada mode pengirim, kamu harus menulis byte selanjutnya kedalam TWDR untuk dikirim. Sebagaimana seperti yang telah kita sebutkan, kamu dapat mengakses TWDR saja ketika TWIE diset 1; sebaliknya bentrokan akan terjadi. Ini berarti Data Register tidak dapat digunakan oleh pengguna sebelum interrupt pertama muncul.

Hal | 14

Page 15: I2C bus protocol

TWI Address Register (TWAR)

TWAR berisi 7-bit alamat slave yang mana TWI akan merespon ketika bekerja sebagai slave. Bit ke-8 (LSB) dari TWAR adalah TWGCE (TWI General Call Recognition Enable). TWGCE mengatur pengenalan dari alamat panggilan umum (00). Jika bit ini diset 1, menerima alamat panggilan umum akan menyebabkan sebuah permintaan interrupt.

Bagian 3: Pemrograman AVR TWI dalam Bahasa Assembly dan C

Pada bagian ini kita akan mempelajari pemrograman TWI dalam bahasa Assembly dan C. disini kita akan fokuskan pada bentuk yang paling simple dari pemrograman TWI tanpa memeriksa status register. Pada banyak penggunaan, jika anda tidak berhadapan dengan sistem yang genting dan tidak ada lebih dari satu master pada jalur tunggal, kamu dapat menggunakan cara ini. Jika kamu ingin berhadapan dengan banyak master(multi-master) atau desain yang agak rumit kamu harus memeriksa nilai dari status register flag. Pemrograman TWI dengan memeriksa nilai dari status flag akan dibahas kemudian.

Pada protocol I2C, sebuah device dapat berlaku sebagai master atau slave. Pada bagian ini kita akan menjelaskan langkah pemrograman pada setiap mode.

Pemrograman AVR TWI pada mode operasi master

Untuk bekerja pada mode master, kita harus dapat menginisialisasi TWI, mengirim sebuah kondisi START, mengirim atau menerima data, dan mengirim sebuah kondisi STOP. Lebih lanjut kita akan menjelaskan setiap fungsi-fungsinya.

Inisialisasi

Untuk menginisialisasi modul TWI untuk digunakan pada mode operasi master, kita harus mengerjakan beberapa hal ini:

1. Mengatur frekuensi clock modul TWI dengan mengatur nilai dari register TWBR dan bit TWPS pada register TWSR.

2. Meng-enable (memperbolehkan) modul TWI dengan mengatur bit TWEN pada register TWCR menjadi 1.

Mengirim kondisi START

Untuk memulai pengiriman data pada mode master, kita harus mengirim kondisi START. Hal ini dikerjakan dengan mengatur TWEN, TWSTA, dan bit TWINT dari register TWCR menjadi 1. Mengatur bit TWEN menjadi 1 akan meng-enable modul TWI. Mengatur bit TWSTA menjadi 1 memerintahkan TWI untuk mengindikasikan sebuah kondisi START ketika bus sedang kosong, dan mengatur bit TWINT

Hal | 15

Page 16: I2C bus protocol

menjadi 1 akan meng-clear flag interrupt untuk menginisialisasi operasi dari modul TWI untuk mengirim kondisi START. Kemudian kita harus menyelidiki flag TWINT pada register TWCR untuk melihat apakah kondisi START dikirim secara sempurna.

Mengirim Data

Untuk mengirim 1 byte data, sesudah mengirimkan kondisi START, kita harus mengerjakan beberapa langkah ini:

1. Menyalin (copy) byte data ke TWDR2. Set bit TWEN dan TWINT dari register TWCR menjadi 1 untuk memulai mengirim byte data.3. Memeriksa flag TWINT pada register TWCR untuk melihat apakah byte data telah dikirim

secara sempurna.

Catat bahwa dikanan setelah kondisi START, kita harus mengirim SLA+W (Slave Address + Write) atau SLA+R(Slave Address+Read). Sebagaimaan telah kita sebutkan pada bagian pertama, dikanan sesudah mengirimkan SLA+W kita harus menulis ke slave dan dikanan sesudah mengirimkan SLA+R kita harus membaca dari sini. Untuk mengirim SLA+R, SLA+W dan untuk menuliskan sebuah byte data ke slave kita menggunakan sebuah fungsi yang disebut I2C_WRITE.

Menerima Data

Untuk menerima sebuah byte data, sesudah mengirimkan SLA+R, kita harus mengerjakan beberapa langkah:

1. Set bit TWEN dan TWINT dari register TWCR menjadi 1 untuk memulai menerima sebuah byte data. Catat bahwa jika kamu ingin mengembalikan ACK sesudah menerima data kamu harus juga men-set bit TWEA dari register TWCR menjadi 1.

2. Menyelidiki flag TWINT pada register TWCR untuk melihat apakah sebuah byte data telah diterima secara sempurna.

3. Menyalin (copy) byte yang diterima dari TWDR ke register yang lain untuk menyimpan ini.

Mengirim kondisi STOP

Untuk menghentikan transfer data, kita harus mengirimkan sebuah kondisi STOP. Hal ini dikerjakan dengan menset bit TWEN, TWSTO dan TWINT dari register TWCR menjadi 1. Catat bahwa kita tidak bisa memeriksa flag TWINT sesudah mengirim kondisi STOP.

Program 1 dibawah ini menunjukan bagaimana sebuah master menulis 1111 0000 ke slave dengan alamat 110 1000.

Hal | 16

Page 17: I2C bus protocol

/* * i2c.asm * * Created: 15-Dec-12 5:42:29 PM * Author: Mahmuddin */ ;Tested OK.include "m32def.inc"

LDI R21,HIGH(RAMEND) ; set up StackOUT SPH,R21LDI R21,LOW(RAMEND)OUT SPL,R21

CALL I2C_INIT ; inisialisasi modul TWICALL I2C_START ; mengirimkan kondisi STARTLDI R27,0b11010000 ; SLA (1101000)+W(0)CALL I2C_WRITE ; menulis R27 ke bus I2CLDI R27,0b11110000 ; data untuk dikirimCALL I2C_WRITE ; menulis R27 ke bus I2CCALL I2C_STOP ; mengirim kondisi START

HERE: RJMP HERE ; tunggu disini selamanya;****************************************************************I2C_INIT:

LDI R21,0OUT TWSR,R21 ; set bit prescaler ke 0LDI R21,0x47 ; masukan 0x47 ke R21OUT TWBR,R21 ; set clock freq ke 50k (8MHz XTAL)LDI R21,(1<<TWEN) ; copy 0x04 kedalam R21OUT TWCR,R21 ; enable TWIRET

;****************************************************************I2C_START:

LDI R21,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)OUT TWCR,R21 ; kirim kondisi START

WAIT1:IN R21, TWCR ; baca control register kedalam R21SBRS R21,TWINT ; skip baris selanjutnya jika TWINT bernilai

1RET

;*****************************************************************I2C_WRITE:

OUT TWDR,R27 ; masukkan 0b11110000 kedalam TWDRLDI R21,(1<<TWINT)|(1<<TWEN)OUT TWCR,R21 ; mengatur TCRW untuk mengirim TWDR

WAIT3:IN R21,TWCR ; baca kontrol register kedalam R21SBRS R21,TWINT ; skip baris selanjutnya jika TWINT bernilai

1RJMP WAIT3 ; loncat ke WAIT3 jika TWINT bernilai 1RET

;******************************************************************I2C_STOP:

LDI R21,(1<<TWINT)|(TWSTO)|(1<<TWEN)OUT TWCR,R21 ; mengirim kondisi STOP

Hal | 17

Page 18: I2C bus protocol

RET

Program 2 di bawah ini menunjukkan bagaimana membaca 1 byte data dari sebuah slave dengan alamat 1001100 dan menampilkan hasilnya pada PORT A.

/* * kirimkeportA.asm * * Created: 16-Dec-12 8:26:18 PM * Author: Mahmuddin */

;tested OK.include "m32def.inc"

ldi r21,high(ramend)out sph,r21ldi r21,low(ramend) out spl,r21

ldi r21,$ff ; masukan $FF (0b11111111) ke R21out ddra,r21 ; PORT A sebagai output

call I2C_INIT ; inisialisasi modul TWIcall I2C_START ; mengirim kondisi STARTldi r27,0b10011001 ; SLA(1001100) + R(1)call I2c_write ; tulis R27 ke bus I2Ccall I2c_read ; tulis R27 ke bus I2cout porta,r27 ; kirim kondisi STOP

here: rjmp here;*******************************************************i2c_init:

ldi r21,0out twsr,r21 ; set bit prescaler ke 0ldi r21,$47 ; copy $47 kedalam R21out TWBR,R21 ; frekuensi SCL => 50k untuk XTAL 8MHzldi r21,(1<<twen) ; copy 0x04 kedalam R21out twcr,r21 ; meng-enable TWIret

;*******************************************************i2c_start:

ldi r21,(1<<twint)|(1<<twsta)|(1<<twen)out twcr,r21 ; kirim kondisi START

wait1:in r21,twcr ; kirim register kontrol ke R21sbrs r21,twint ; skip baris selanjutnya jika twint bernilai 1rjmp wait1 ; lompat ke wait1 jika twint bernilai 1ret

;*******************************************************i2c_read:

ldi r21,(1<<twint)|(1<<twen)out twcr,r21

wait2:in r21,twcr ; baca kontrol register kedalam r21sbrs r21,twint ; skip baris selanjutnya jika twint bernilai 1rjmp wait2 ; lompat kw wait2 jika twint bernilai 0in r27,twdr ; baca data yang diterima kedalam r21

Hal | 18

Page 19: I2C bus protocol

ret;********************************************************i2c_write:

out twdr,r27 ; copy byte data kedalam TWDRldi r21,(1<<twint)|(1<<twen)out twcr,r21 ; mengatur twcr untuk mengirim TWDR

wait3:in r21,twcr ; baca kontrol register kedalam r21sbrs r21,twint ; skip baris selanjutnya jika twint bernilai 1rjmp wait3 ; loncat ke wait3 jika twint bernilai 1ret

;***********************************************************i2c_stop:

ldi r21,(1<<twint)|(1<<twsto)|(1<<twen)out twcr,r21 ; kirim kondisi STOPret

Pemrograman Bahasa C untuk AVR TWI pada mode operasi Master

Program 3 di bawah ini menunjukan bagaimana sebuah master menulis 1111 0000 ke slave dengan alamat 1101000. Program ini adalah program c dari program 1.

Program 4 menunjukan bagaimana sebuah master membaca sebuah slave dengan alamat 1101000 dan menampilkannya pada PORTA. Program ini adalah versi C dari program 2.

Program 3/* * i2cdenganc.c * * Created: 16-Dec-12 9:01:24 PM * Author: Mahmuddin */

#include <avr/io.h>

void i2c_write(unsigned char data){

TWDR = data;TWCR = (1<<TWINT)|(1<<TWEN);while ((TWCR & (1<<TWINT))== 0);

}

//************************************************void i2c_start(void){

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);while((TWCR & (1<<TWINT))== 0);

}

//***********************************************void i2c_stop(){

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);}

Hal | 19

Page 20: I2C bus protocol

//***********************************************void i2c_init(void){

TWSR = 0x00; //set bit prescaler menjadi 0TWBR = 0x47; //frekuensi SCL 50k untuk XTAL = 8MTWCR = 0x04; //enable modul TWI

}

//***********************************************

int main(void){ i2c_init();

i2c_start(); //kirim kondisi STARTi2c_write(0b11010000); //kirim SLA + W(0)i2c_write(0b11110000); //kirim data 0b1111 0000i2c_stop(); //kirim kondisi STOPwhile(1); //stay here foreverreturn 0;

}

Program 4/* * kirimportAversiC.c * * Created: 16-Dec-12 9:16:22 PM * Author: Mahmuddin */

#include <avr/io.h>

void i2c_init(void){

TWSR = 0x00; //set bit prescaler ke 0TWBR = 0x47; //frekuensi SCL 50k untuk XTAL = 8MTWCR = 0x04; //enable modul TWI

}

//******************************************************void i2c_start(void){

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);while ((TWCR & (1<<TWINT)) == 0);

}

//******************************************************void i2c_write(unsigned char data){

TWDR = data;TWCR = (1<<TWINT)|(1<<TWEN);while ((TWCR & (1<<TWINT)) == 0);

}//*******************************************************unsigned char i2c_read(unsigned char isLast){

if(isLast == 0) //jika ingin membaca lebih dari 1 byte

Hal | 20

Page 21: I2C bus protocol

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);else

TWCR = (1<<TWINT)|(1<<TWEN);while ((TWCR & (1<<TWINT)) == 0);return TWDR;

}//*********************************************************void i2c_stop(){

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);}//**********************************************************

int main(void){ unsigned char i = 0;

DDRA = 0xFF; //PORT A sebagai outputi2c_init(); //inisialisasi TWI untuk mode masteri2c_start(); //kirim kondisi STARTi2c_write(0b11010001); //kirim SLA + R(1)i = i2c_read(1); //baca hanya 1 byte dari dataPORTA = i; //tampilkan byte pada PORTAi2c_stop(); //kirim kondisi STOPwhile(1);return 0;

}

Pemrograman AVR TWI pada mode slave

Untuk bekerja dalam mode slave, kita harus bisa menginisialisasi TWI dan kita juga harus dapat mengirim atau menerima data. Pada mode slave kita tidak bisa mengirim kondisi START dan STOP. Sebuah device slave harus mendengar ke bus dan menunggu dialamati oleh device master atau panggilan umum (general call).

InisialisasiUntuk menginisialisasi modul TWI untuk beroperasi pada mode slave, kita harus mengerjakan

beberapa hal berikut:1. Set alamat slave dengan mengatur nilai untuk register TWAR. Sebagaimana kita sebutkan

sebelumnya, 7-bit teratas dari register TWAR adalah alamat slave, dan bit ke-8 adalah TWGCE. Jika kamu mensetting bit TWGCE menjadi 1, TWI akan merespon alamat panggilan umum ($00); jika tidak; maka panggilan umum akan diabaikan.

2. Meng-enabel modul TWI dengan mengatur bit TWEN pada register TWCR menjadi 13. Set bit TWEN, TWINT dan TWEA menjadi 1 untuk meng-enable TWI dan pembuatan

acknowledge.Catat bahwa kita tidak dapat menggabungkan langkah 2 dan 3 menjadi satu langkah. Kita harus

meng-enable modul TWI sebelum mengerjakan langkah 3.

Mendengarkan BusSesudah menginisialisasi modul TWI, sebuah device slave harus mendengarkan bus untuk

menemukan ketika slave dialamati oleh device master. Ketika modul TWI menemukan dirinya dialamati pada bus, slave membalas dengan ACK dan men-set flag TWINT pada register TWCR menjadi 1. Kita harus menyelidiki flag TWINT untuk melihat ketika slave dialamati dengan device master.

Hal | 21

Page 22: I2C bus protocol

Mengirim DataSesudah slave dialamati dengan device master untuk dibaca, kita harus mengerjakan beberapa

hal ini untuk mengirim 1 byte data:1. Menyalin byte data ke TWDR2. Set bit TWEN, TWEA, dan TWINT dari register TWCR menjadi 1 untuk memulai mengirim byte.

Catat bahwa jika kamu berharap tidak menerima ACK sesudah penerimaan data kamu dapat meninggalkan TWEA dalam kondisi clear. Hal ini tidak akan berpengaruh pada pembuatan ACK oleh master dan hanya akan merubah keadaan internal dari modul TWI. Kami menyarankan anda untuk men-set bit TWEA menjadi 1 dari register TWCR bagaimanapun.

3. Menyelidiki flag TWINT pada register TWCR untuk melihat ketika byte telah selesai dikirim.

Menerima DataSesudah slave dialamati oleh device master, kita harus mengerjakan beberapa hal berikut untuk

menerima byte data:1. Set bit TWEN dan TWINT dari register TWCR menjadi 1 untuk memulai menerima 1 byte. Catat

bahwa jika kamu ingin mengembalikan ACK sesudah menerima data kamu juga harus men-set bit TWEA dari register TWCR menjadi 1.

2. Menyelidiki flag TWINT pada register TWCR untuk melihat apakah 1 byte telah diterima secara sempurna.

3. Salin byte yang diterima dari TWDR ke register lain untuk menyimpan byte tersebut.

Program 5 dan 6 berikut menunjukan bagaimana untuk menginisialiasi modul TWI untuk beroperasi pada mode slave. Pada program 5 modul TWI mendengarkan bus dan menunggu sampai dialamati oleh device master. Kemudian slave mengirim huruf ‘G’ ke device master.

Program 5/* * kirim_ke_master.asm * * Created: 16-Dec-12 10:14:12 PM * Author: Mahmuddin */

.include "m32def.inc"

ldi r21,high(ramend) ;set up stackout sph,r21ldi r21,low(ramend)out spl,r21

call i2c_init ;inisialisasi modul TWI sebagai slavecall i2c_listen ;dengarkan bus untuk dialamati oleh masterldi r21,'G' ;masukan 'G' ke dalam R21call i2c_write ;tulis byte ke bus

here: rjmp here

;********************************************************************i2c_init:

ldi r21,0x10 ;masukan alamat slave 00010000 kedalam R21out twar,r21 ;masukan TWI Address Register

Hal | 22

Page 23: I2C bus protocol

ldi r21,(1<<twen) ;masukan 0x04 kedalam r21out twcr,r21 ;enable TWIldi r21,(1<<twint)|(1<<twen)|(1<<twea)out twcr,r21 ;enable TWI dan ACK(tidak dapat diabaikan)ret

;*********************************************************************i2c_listen:w1:

in r21,twcr ;baca register kontrol kedalam r21sbrs r21,twint ;skip instruksi selanjutnya jika TWINT

adalah 1rjmp w1 ;loncat ke w1 jika TWINT bernilai 0ret

;*********************************************************************i2c_write:

out twdr,r21 ;copy r21 ke twdrldi r21,(1<<twint)|(1<<twen)out twcr,r21

w2:in r21,twcr ;baca control register kedalam r21sbrs r21,twint ;lewati baris selanjutnya jika twint adalah

1rjmp w2 ;loncat ke w2 jika twint adalah 0ret

Pada program 6 di bawah ini modul TWI mendengerkan ke bus dan menunggu sampai dialamati oleh master. Kemudian slave membaca 1 byte dari master dan menampilkannya pada Port A.

Program 6/* * i2c.asm * * Created: 16-Dec-12 10:41:44 PM * Author: Mahmuddin */

.include "m32def.inc"

ldi r21,high(ramend) ;set up stackout sph,r21ldi r21,low(ramend)out spl,r21

ldi r21,0xff ;copy 0xff kedalam r21out ddra,r21 ;set Port A sebagai output

call i2c_init ;inisialisasi modul TWI sebagai slavecall i2c_listen ;dengarkan bus untuk dialamaticall i2c_read ;baca 1 byte dan salin ke r27out porta,r27 ;salin r27 ke porta

here:rjmp here ;wait here forever

;***************************************************************i2c_init:

ldi r21,0x10 ;masukan 00010000 kedalam r21out twar,r21 ;set alamat registerldi r21,(1<<twen) ;salin 0x04 kedalam r21

Hal | 23

Page 24: I2C bus protocol

out twcr,r21 ;enable TWIldi r21,(1<<twint)|(1<<twen)|(1<<twea)out twcr,r21 ;meng-enable TWI dan ACK (tidak dapat diabaikan)ret

;****************************************************************i2c_listen:w1:

in r21,twcr ;baca register kontrol kedalam r21sbrs r21,twint ;lewati instruksi selanjutnya jika twint bernilai

1rjmp w1 ;lompat ke w1 jika TWINT bernilai 0ret

;******************************************************************i2c_read:

ldi r21,(1<<twint)|(1<<twen)|(1<<twea)out twcr,r21 ;mengatur twcr untuk menerima twdr

w2:in r21,twcr ;baca kontrol register kedalam r21sbrs r21,twint ;lewati baris selanjutnya jika TWINT bernilai 1rjmp w2 ;loncat ke w2 jika twint bernilai 0in r27,twdr ;copy data yang diterima kedalam r27ret

Pemrograman Bahasa C untuk AVR TWI pada mode Slave

Program 7 ini adalah bahasa c dari program 5. Program 7 menunjukan bagaimana untuk menginisialisasi modul TWI untuk beroperasi pada mode slave. Pada program 7 modul TWI mendengar bus dan menunggu sampai dialamati oleh device master. Kemudian slave mengirimkan huruf ‘G’ ke device master.

Program 7/* * program7.c * * Created: 16-Dec-12 11:09:08 PM * Author: Mahmuddin */

#include <avr/io.h>

void i2c_initSlave(unsigned char slaveAddress){

TWCR = 0x04; //meng-enable TWITWAR = slaveAddress; //set slave addressTWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); //init TWI modul

}

//************************************************************void i2c_send(unsigned char data){

TWDR = data; //salin data ke twdrTWCR = (1<<TWINT)|(1<<TWEN); //memulai pengirimanwhile ((TWCR&(1<<TWINT))==0); //tunggu sampai selesai

}

Hal | 24

Page 25: I2C bus protocol

//**************************************************************void i2c_listen(){

while ((TWCR&(1<<TWINT))==0); //tunggu sampai dialamati}

//**************************************************************

int main(void){ i2c_initSlave(0x10); //init modul TWI sebagai

//slave dengan alamat//0b0001000 dan tidak//menerima panggilan umum

i2c_listen(); //dengar sampau dialamatii2c_send('G'); //kirim huruf 'G'while(1)

return 0;}

Program 8 di bawah ini adalah versi c dari program 6. Pada program 8 ini modul TWI mendengar ke bus dan menunggu sampai dialamati oleh master. Kemudian slave membaca 1 byte data dari master dan menampilkannya pada Port A.

Program 8/* * program8.c * * Created: 16-Dec-12 11:26:17 PM * Author: Mahmuddin */

#include <avr/io.h>

void i2c_initSlave(unsigned char slaveAddress){

TWCR = 0x04; //meng-enable modul TWITWAR = slaveAddress; //set alamat SlaveTWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); //init modul TWI

}

//***********************************************************unsigned char i2c_receive(unsigned char isLast){

if (isLast == 0) //jika ingin membaca lebih dari 1 byte

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);else

TWCR = (1<<TWINT)|(1<<TWEN);while ((TWCR & (1<<TWINT)) == 0); // tunggu sampai selesaireturn (TWDR);

}

//**************************************************************

Hal | 25

Page 26: I2C bus protocol

void i2c_listen(){

while ((TWCR & (1<<TWINT)) == 0); //tunggu sampai dialamati}

//**************************************************************int main(void){ DDRA = 0xFF; //init modul TWI sebagai

//slave dengan alamat//0b0001000 dan tidak//menerima panggilan umum

i2c_listen(); //mendengar untuk dialamatiPORTA = i2c_receive(1);while(1) //stay here forever

return 0;}

Bagian 4: Hubungan DS1307 dan Pemrogramannya

Real-time clock (RTC) adalah device yang secara luas digunakan untuk menyediakan waktu yang akurat dan informasi data untuk banyak aplikasi. Banyak sistem contohnya x86 PC terdapat sebuah chip pada motherboardnya. Chip RTC pada x86 PC menyediakan komponen waktu dari jam, menit dan detik, pada tambahannya komponen tanggal/kalender seperti tahun, bulan, dan hari. Banyak chip RTC menggunakan sebuah batter internal, yang mana menjaga waktu dan tanggal bahkan ketika power dimatikan. Meskipun beberapa mikrokontroler, seperti DS5000T dan beberapa AVR, dating dengan embedded RTC yang telah siap di dalam chipnya, kita harus menghubungkan sangat banyak mayoritas dari mereka ke chip RTC external. Satu dari banyak penggunaan yang luas dari chip RTC adalah DS12887 dari Dallas Semiconductor/Maxim Corp. chip ini dapat ditemukan pada banyak x86 PC. IBM PC/AT aslinya menggunakan RTC MC14618B dari Motorola (sekarang Freescale). DS12887 adalah pengganti dari chip tersebut. Chip DS12887 menggunakan batrre litium internal untuk menjaga pengoperasian selama 10 tahun pada ketiadaan power eksternal. DS12887 adalah RTC parallel dengan 8 pin untuk bus data. DS1307 adalah RTC serial dengan sebuah bus I2C. Pada bagian ini, kita menghubungkan dan memprogram DS1307 RTC. Berdasarkan datasheet DS1307 dari Maxim, “waktu/kalender menyediakan detik, menit, jam, hari, tanggal, bulan, dan informasi tahun. Tanggal akhir bulan secara otomatis disesuaikan untuk bulan dengan kurang dari 31 hari, termasuk mengkoreksi tahun kabisat. Operasi waktu baik format 24 jam atau 12 jam dengan indicator AM/PM. DS1307 telah dibangun dengan sirkuit power-sense yang mendeteksi kegagalan power dan secara otomatis merubah ke suplai batterai.” DS1307 tidak mendukung pilihan Daylight Saving Time (waktu yang menunjukkan satu jam lebih cepat daripada biasa). Kemudian, kita jelaskan pin dari DS1307. Lihat gambar 14.

X1-X2

X1-X2 adalah pin input yang memperbolehkan hubungan DS1307 ke oscillator Kristal eksternal untuk menyediakan sumber clock ke chipnya. Kita harus menggunakan Kristal quartz standard 32,768 kHz. Akurasi dari clock tergantung pada kualitas dari oscillator Kristal. Panas dapat menyebabkan sebuah simpangan pada oscillator. Untuk menghindari ini, kita dapat menggunakan chip DS32KHZ, yang mana

Hal | 26

Page 27: I2C bus protocol

secara otomatis menyelaraskan variasi temperature. Catat bahwa ketika menggunakan DS32KHZ atau generator clock yang sama, kita hanya perlu menghubungkan X1 karena X2 loopback tidak diperlukan.

Gambar 14. DS1307 Pin Out

Vbat

Pin 3 dapat di hubungkan ke battery litium external +3 V, dengan cara demikian maka akan menyediakan sumber power ke chip ketika tegangan supply eksternal tidak tersedia. Kita harus menyambungkan pin ini ke ground jika tidak digunakan. Sebuah batrre litium 48mAh dapat menyediakan tenaga yang diperlukan selama lebih dari 10 tahun untuk memback-up chip.

GND

Pin 4 adalah ground

SDA (Serial Data)

Pin 5 adalah pin SDA dan harus dihubungkan ke jalr SDA dari bus I2C

SCL(Serial Clock)

Pin 6 adalah pin SCL dan harus dihubungkan ke jalur SCL dari bus I2C

SWQ/OUT

Pin 7 adalah pin output yang menyediakan frekuensi 1 kHz, 4 kHz, 8 kHz, atau 32 kHz jika di-enable. Pin ini memerlukan sebuah resistor eksternal pull-up untuk membuat frekuensi karena pin ini bersifat open drain. Jika kamu tidak ingin menggunakan pin ini kamu dapat mengabaikan eksternal pull-up resistor. Kita akan lihat secara singkat bagaimana mengatur pin ini.

Vcc

Pin ke-8 digunakan sebagai tegangan sumber utama bagi chip. Tegangan sumber utama ini biasasnya sebesar +5V. ketika Vcc jatuh dibawah level Vbat, DS1307 mengalihkan ke Vbat dan batrre eksternal litium yang menyediakan power ke RTC. Berdasarkan datasheet DS1307, “selama power-up,

Hal | 27

Page 28: I2C bus protocol

device mengalihkan dari Vbat ke Vcc ketika Vcc1 lebih besar dari Vbat+0,2 Volt”. Catat juga bahwa device dapat digunakan jika hanya ketika Vcc lebih dari 1,25 x Vbat. Karena kita dapat menghubungkan battre litium standar 3V ke pin Vbat, level tegangan Vcc harus tersisa diatas 3,2 V agar supaya Vcc ke sisanya sebagai sumber tegangan utama ke chip, dan Vcc harus lebih besar dari 3,75 jika kamu ingin menggunakan chip ini.

Gambar 15. Pilihan hubungan DS1307 (maxim/dallas semiconductor)

Peta Alamat dari DS1307

DS1307 mempunyai jumlah RAM sebesar 64bytes dengan alamat 00-3Fh. Tujuh lokasi pertama, 00-06 ditetapkan untuk nilai waktu dan tanggal RTC. Byte selanjutnya digunakan untuk control register. Control register terletak pada alamat 07 hex. 56 byte selanjutnya dari alamat 07h – 3Fh, disediakan untuk tujuan penyimana data umum. Ini berarti seluruh 64 byte dari RAM dapat digunakan secara langsung untuk dibaca atau ditulis. Gambar 16 menunjukan peta alamt dari DS1307. Kemudian, kita mempelajari register control dan cara mengakses waktu dan tanggal pada DS1307.

Gambar 16. Block Diagram DS1307 (maxim/dallas semiconductor)

Hal | 28

Page 29: I2C bus protocol

Kontrol Register DS1307

Sebagaimana ditunjukan pada gambar 16, register control mempunyai alamat pada 07h. pada register control DS1307, bit control adalah fungsi dari pin SQW/OUT. Pada gambar 17 kamu lihat fungsi setiap bit.

Gambar 17. DS1307 Control Register (alamat lokasi menulis adalah 8Fh)

OUT (Output Control) jika keluaran gelombang kotak didisable, menset bit OUT menjadi 1 akan membuat pin SQW/OUT menjadi rendah dan men-clear bit OUT menjadi 0 akan membuat pin SQW/OUT menjadi tinggi.

SQWE(Square wave enable) jika bit ini diset HIGH, maka output oscillator akan di enable jika tidak makan akan didisable.

RS1-RS0 (rate select) bit ini memilih frekuensi output dari output oscillator menurut table berikut.

RS1 RS0 Output Frekuensi

0 0 1Hz

0 1 4,096 kHz

1 0 8,192 kHz

1 1 32,768 kHz

Bit CH pada alamat 00

Salah satu bit yang penting pada lokasi alamat Detik (Second) pada DS1307 adalah bit CH (Clock Halt). Ini adalah bit ke-7 dari lokasi alamat 00. Menset bit CH menjadi 1 akan mendisable osilator, sementara jika diset 0 akan mengenable osilator. Bit CH tidak ditentukan batas-batasnya ketika reset. Dalam rangka mengenable osilator, kita harus mengclear CH selama pengaturan inisial.

Lokasi Alamat Waktu dan Tanggal dan modenya

Alamat byte 0-6 diset untuk waktu dan tanggal, sebagimana diperlihatkan pada gambar 16. DS1307 menyediakan data dalam format BDC saja. Catat bahwa jangkauan data untuk mode jam. Kita dapat memilih mode 12 atau 24 jam dengan bit 6 dari lokasi Hour 02h. ketika D6 =1, mode 12 jam akan dipilih, dan bila D=0 maka akan memilih mode 24 jam. Pada mode 12 jam, kita harus memutuskan AM dan PM dengan bit 5. Jika D5=0, maka akan dipilih AM dan jika D5=1 makan akan memilih PM. Lihat contoh di bawah ini.

Contoh:

Cari harga untuk lokasi alamat $02 untuk menset jam ke: (a) 21, (b)11 AM, (c)12 PM.

Hal | 29

Page 30: I2C bus protocol

Solusi:

(a). untuk mode 24 jam, kita harus menset D6=0. Untuk itu kita tempatkan 0010 001 pada lokasi $02, yang mana bernilai 21 dalam bilangan BCD

(b). untuk mode 12 jam, kita harus menset D6=1. Juga kita harus menset D5=0 untuk AM. Untuk itu kita menempatkan 0101 0001 pada lokasi $02 yang mana bernilai 51 dalam bilangan BCD.

(c). untuk mode 12 jam, kita harus menset D6=1. Juga kita harus menset D5=1 untuk PM. Untuk itu kita menempatkan 0111 0010 pada lokasi $02 yang amna bernilai 72 dalam bilangan BCD.

Register Pointer

Pada DS1307 ada sebuah register pointer yang menetapkan byte yang akan di akses pada perintah read atau write selanjutnya. Sesudah setiap operasi read atau write, isi dari register pointer secara otomatis naik (increment). Ini sangat berguna dalam read atau write multibyte.

Menulis ke DS1307

Untuk menset nilai dari register pointer dan menulis satu atau lebih byte data ke DS1307, kamu dapat menggunakan langkah-langkah berikut ini:

1. Untuk mengakses DS1307 untuk operasi menulis, sesudah mengirimkan sebuah kondisi START, kamu harus mengirimkan alamat dari DS1307 (1001101) diikuti oleh angka 0 untuk mengindikasikan sebuah operasi menulis.

2. Byte pertama dari data pada operasi menulis akan menset register pointer. Sebagai contohnya, jika kamu ingin mengakses register control kamu harus mengirim 0x07.

3. Jika kamu hanya ingin untuk menset register pointer kamu haruus melewati langkah ini. Jika kamu ingin menulis satu atau lebih byte data, kamu harus mengirimkan mereka 1 byte dalam 1 waktu. Ingat bahwa register pointer secara otomatis naik dan kamu dapat dengan mudah mengirimkan byte data ke lokasi berurutan dalam mode miltibyte burst write.

4. Mengirimkan sebuah kondisi STOP

Membaca dari DS1307

Catat bahwa sebelum membaca 1 byte kamu harus mengisi alamat dari byte tersebut ke register pointer dengan mengerjakan sebuah operasi penulisan sebagaimana disebutkan sebelumnya.

Untuk membaca 1 atau lebih byte data dari DS1307 kamu harus mengerjakan berberapa hal berikut:

1. Untuk mengakses DS1307 untuk operasi membaca, sesudah mengirim sebuah kondisi START, kamu harus mengirim alamat dari DS1307 (1001101) diikuti oleh 1 untuk mengindikasikan sebuah operasi membaca.

2. Sekarang kamu dapat membaca 1 atau lebih byte data. Ingat bahwa register pointer mengindikasikan alamat mana yang akan dibaca. Catat juga bahwa register pointer secara

Hal | 30

Page 31: I2C bus protocol

otomatis bertambah(increment) dan kamu dapat dengan mudah menerima byte data berurutan dalam multibyte burst read.

3. Mengirim kondisi STOP bit.

Mengatur Waktu dalam bahasa Assembly

Program 9 di bawah ini menginisialisasi clock pada 16:68:55 menggunakan mode 24 jam. Program ini menggunakan operasi single-byte untuk menulis ke register kontrol dari DS1307 dan mode multibyte burst untuk menulis detik, menit dan jam. Catat bahwa pada program ini kita mengasumsikan bahwa hanya ada 1 master dalam bus dan kita tidak mengurusi status register.

/* * DS1307.asm * * Created: 17-Dec-12 8:36:49 PM * Author: Mahmuddin */

ldi r21,high(ramend) ;setup stack out sph,r21 ldi r21,low(ramend) out spl,r21

call i2c_init ;inisialisasi modul i2c ldi r21,0b11010000 ;SLA(1101000) + W(0) call i2c_send ;kirim R21 ke i2c bus ldi r21,0x07 ;set register pointer ke 07 call i2c_send ;untuk mengakses kontrol register ldi r21,0x00 ;set kontrol register = 0 call i2c_send ;kirim r21 ke i2c bus call i2c_stop ;kirim sebuah kondisi STOP

call delay

call i2c_start ;kirim sebuah kondisi START ldi r21,0b11010000 ;SLA (1101000) + W(0) call i2c_send ;kirim r21 ke i2c bus ldi r21,0x00 ;set register pointer ke 0 call i2c_send ;kirim r21 ke i2c bus ldi r21,0x55 ;set detik ke 0x55 = 55 BCD call i2c_send ;kirim r21 ke i2c send ldi r21,0x58 ;set menit ke 0x58 = 58 BCD call i2c_send ;kirim r21 ke i2c bus ldi r21,0b00010110 ;jam = 16 dalam mode 24 jam call i2c_send ;kirim r21 ke i2c bus

call i2c_stop ;kirim sebuah kondisi STOP

here: rjmp here ;wait here forever

;*************************************************************** i2c_init:

ldi r21,0out twsr,r21 ;set prescaler bit ke 0ldi r21,0x47 ;salin 0x47 ke dalam r21

Hal | 31

Page 32: I2C bus protocol

out twbr,r21 ;frek SCL 50kHz untuk 8 MHz XTALldi r21,(1<<twen) ;salin 0x04 ke dalam r21out twcr,r21 ;meng-enable TWIret

;******************************************************************i2c_start:

ldi r21,(1<<twint)|(1<<twsta)|(1<<twen)out twcr,r21 ;kirim sebuah kondisi START

w1: in r21,twcr ;baca register kontrol kedalam r21sbrs r21,twint ;tutup interrupt flagrjmp w1 ;loncat ke w1 jika twint bernilai 1ret

;****************************************************************i2c_send:

out twdr,r21 ;salin SLA+W kedalam TWDRldi r21,(1<<twint)|(1<<twen)out twcr,r21 ;mengatur TWCR untuk mengirim TWDR

w2: in r21,twcr ;baca register kontrol kedalam r21sbrs r21,twint ;tutup interrupt flagrjmp w2 ;lompat ke w2 jika twint bernilai 1ret

;****************************************************************i2c_stop:

ldi r21,(1<<twint)|(1<<twsto)|(1<<twen)out twcr,r21 ;kirim kondisi STOP

w3: in r21,twcr ;baca kontrol register kedalam r21sbrs r21,twsto ;tutup interrupt flagrjmp w3ret

;***************************************************************delay:

ldi r22,0xffa1: dec r22 ;kirim kondisi STOP

nopbrne a1ret

Pengaturan Tanggal dalam Bahasa Assembly

Progam 10 menunjukan bagaimana untuk menset tanggal ke 19 Oktober 2009. Program ini menggunakan operasi single-byte untuk menulis kedalam control register dari DS1307 dan mode multibyte burst untuk menulis hari, bulan, dan tahun. Sebagaimana yang kamu lihat pada program, untuk mengakses lokasi dari tanggal, kamu harus menulis 0x04 kedalam register pointer dan kemudian kamu dapat menggunakan multibyte burst write untuk menulis nilai dari bulan dan tahun pada lokasi yang berurutan. Catat juga bahwa pada kode ini kita mengasumsikan bahwa hanya ada 1 master pada bus dan kita tidak mengurusi dengan memeriksa status register.

/* * Program10.asm

Hal | 32

Page 33: I2C bus protocol

* * Created: 18-Dec-12 5:52:32 AM * Author: Mahmuddin */

.include "m32def.inc"

ldi r21,high(ramend) ;set up stackout sph,r21ldi r21,low(ramend)out spl,r21

call i2c_init ;inisialisasi modul i2c

call i2c_start ;mengirim sebuah kondisi STARTldi r21,0b11010000 ;SLA (1101000) + W (0)call i2c_send ;mengirim r21 ke i2c busldi r21,0x07 ;set register pointer ke 07call i2c_send ;untuk mengakses register kontrolldi r21,0x00 ;set kontrol register = 0call i2c_send ;mengirim r21 ke i2c buscall i2c_stop ;mengirim sebuah kondisi STOP

call delay

call i2c_start ;mengirim sebuah kondisi STARTldi r21,0b11010000 ;SLA (1101000) + W (0)call i2c_send ;mengirim r21 ke i2c busldi r21,0x04 ;menset register pointer ke 4call i2c_send ;mengirim r21 ke i2c busldi r21,0x19 ;set hari ke 0x19 = 19 BCDcall i2c_send ;mengirim r21 ke i2c busldi r21,0x10 ;set bulan ke 0x10 = 10 BCDcall i2c_send ;mengirim r21 ke i2c busldi r21,0x09 ;set tahun ke 0x09 = 09 BCDcall i2c_send ;kirim r21 ke i2c buscall i2c_stop ;kirim sebuah kondisi STOPhere: rjmp here ;wait here forever

;*******************************************************************i2c_init:

ldi r21,0out twsr,r21 ;set prescaler bit ke 0ldi r21,0x47 ;salin 0x04 kedalam r21out twbr,r21 ;frek SCL 50 kHz untuk XTAL 8 MHzldi r21,(1<<twen) ;salin 0x04 kedalam r21out twcr,r21 ;meng-enable TWIret

;*******************************************************************i2c_start:

ldi r21,(1<<twint)|(1<<twsta)|(1<<twen)out twcr,r21 ;kirim sebuah kondisi START

w1: in r21,twcr ;baca control register kedalam r21sbrs r21,twint ;skip baris selanjutnya jika twint

;bernilai 1 atau tutup interrup flagrjmp w1 ;loncat ke w1 jika twint bernilai 1ret

;*******************************************************************i2c_send:

Hal | 33

Page 34: I2C bus protocol

out twdr,r21 ;salin SLA+W kedalam TWDRldi r21,(1<<twint)|(1<<twen)out twcr,r21 ;mengatur twcr untuk mengirim twdr

w2: in r21,twcr ;baca control register kedalam r21sbrs r21,twint ;mask interrupt flagrjmp w2 ;loncat ke w2 jika twint bernlai 1ret

;*******************************************************************i2c_stop:

ldi r21,(1<<twint)|(1<<twsto)|(1<<twen)out twcr,r21 ;kirim sebuah kondisi STOP

w3: in r21,twcr ;baca control register kedalam r21sbrs r21,twsto ;mask interrupt flagret

;*******************************************************************delay:

ldi r22,0xffa1: dec r22

nopbrne a1ret

Setting waktu dalam Bahasa C

Program 11 dan 12 ini adalah versi Bahasa C dari dua program terakhir. Catat bahwa kamu harus membuat level optimisasi 0 (optimisasi 0); jika tidak, compiler akan mengabaikan baris “for (int k = 0; k<100;k++)” dan program tidak akan bekerja dengan benar.

Program 11 setting waktu dalam Bahasa C

/* * program11.c * * Created: 18-Dec-12 6:29:03 AM * Author: Mahmuddin */

#include <avr/io.h>void i2c_stop(){

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);}//**********************************************************************void i2c_write(unsigned char data){

TWDR = data;TWCR = (1<<TWINT)|(1<<TWEN);while (!(TWCR & (1<<TWINT)));

}//**********************************************************************void i2c_start(void){

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);while (!(TWCR & (1<<TWINT)));

}

Hal | 34

Page 35: I2C bus protocol

//*********************************************************************void i2c_init(void){

TWSR=0x00; //set prescaler bit ke 0TWBR=0x47; //frek SCL 50k pada XTAL=8MTWCR =0x04; //enable modul TWI

}//*********************************************************************int main(void){

i2c_init(); //inisialiasi modul i2ci2c_start(); //kirim kondisi STARTi2c_write(0b11010000); //alamat DS1307 untuk ditulisi2c_write(0x07); //set register pointer ke 7i2c_write(0x00); //set harga dari lokasi 7 ke 0i2c_stop(); //kirim kondisi STOP

for(int k=0; k<100; k++); //tunggu untuk waktu yang sebentar

i2c_start(); //kirim kondisi STARTi2c_write(0b11010000); //alamat DS1307 untuk ditulisi2c_write(0x07); //set register pointer ke 7i2c_write(0x55); //set detik ke 0x55 = 55 BCDi2c_write(0x58); //set menit ke 0x58 = 58 BCDi2c_write(0b00010110); //set jam = 16 pada mode 24 jami2c_stop(); //kirim kondisi STOP

while(1);return 0;

}

Program 12 Pengaturan Tanggal dalam Bahasa C

/* * program_12.c * * Created: 18-Dec-12 6:50:05 AM * Author: Mahmuddin */

#include <avr/io.h>

void i2c_stop(){

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);}

//****************************************************************void i2c_write(unsigned char data){

TWDR = data;TWCR = (1<<TWINT)|(1<<TWEN);while (!(TWCR & (1<<TWINT)));

}

//****************************************************************void i2c_start(void)

Hal | 35

Page 36: I2C bus protocol

{TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);while (!(TWCR & (1<<TWINT)));

}

//****************************************************************void i2c_init(void){

TWSR = 0x00; //set prescaler ke 0TWBR = 0x47; //frek SCL 50k untuk XTAL-8MTWCR = 0x04; //enable modul TWI

}//***************************************************************int main(void){ i2c_init(); //inisialisasi modul I2C

i2c_start(); //kirim kondisi STARTi2c_write(0b11010000); //alamat DS1307 untuk ditulisi2c_write(0x07); //set register pointer ke 7i2c_write(0x00); //set harga dari lokasi 7 ke 0i2c_stop(); //kirim kondisi STOP

for (int k=0; k<100; k++); //tunggu sebentar

i2c_start(); //kirim kondisi STARTi2c_write(0b11010000); //alamat DS1307 untuk ditulisi2c_write(0x04); //set register pointer ke 4i2c_write(0x19); //set hari ke 0x19 = 19 BCDi2c_write(0x10); //set bulan ke 0x10 = 10 BCDi2c_write(0x09); //set tahun ke 0x09 = 09 BCDi2c_stop(); //kirim kondisi STOP

while(1); //stop disinireturn 0;

}

Mengatur, membaca dan menampilkan waktu dan tanggal dalam bahasa CProgram 13 ini adalah kode C yang lengkap untuk mengatur, membaca dan menampilkan waktu

dan tanggal. Waktu dan Tanggal ini dikirim ke layar IBM PC melalui port serial sesudah mereka dikonversi dari Packed BCD ke ASCII.

Program 13 Sebuah contoh code C DS1307 lengkap/* * program13.c * * Created: 18-Dec-12 7:08:10 AM * Author: Mahmuddin */ #include <avr/io.h>

void usart_init(void){

//inisialisasi pengirim USART untuk data 8-bit tidak berparitas//dan 1 stop bitUCSRB = (1<<TXEN);

Hal | 36

Page 37: I2C bus protocol

UCSRC = (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);UBRRL = 0x33;

}

//*******************************************************************void usart_send(unsigned char data){

while (!(UCSRA & (1<<UDRE))); //tunggu sampai udr kosongUDR = data;

}

//*******************************************************************void usart_send_packedBCD (unsigned char data){

usart_send('0'+(data>>4));usart_send('0'+(data & 0x0F));

}

//*******************************************************************void i2c_init (void){

TWSR = 0x00; //set prescaler bit ke 0TWBR = 0x47; //frek SCL 50k untuk XTAL = 8MTWCR = 0x04; //enable modul TWI

}

//*******************************************************************void i2c_start(void){

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);while (!(TWCR & (1<<TWINT)));

}

//*******************************************************************void i2c_write(unsigned char data){

TWDR = data;TWCR = (1<<TWINT)|(1<<TWEN);while (!(TWCR & (1<<TWINT)));

}

//*******************************************************************unsigned char i2c_read(unsigned char ackVal){

TWCR = (1<<TWINT)|(1<<TWEN)|(ackVal<<TWEA);while (!(TWCR & (1<<TWINT)));return TWDR;

}

//*******************************************************************void i2c_stop(){

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);for (int k=0; k<100; k++); //tunggu sebentar

}

//*******************************************************************void rtc_init(void)

Hal | 37

Page 38: I2C bus protocol

{i2c_init();//inisialisasi modul I2Ci2c_start(); //kirim kondisi STARTi2c_write(0x00); //alamat DS1307 untuk menulisi2c_write(0x07); //mengatur register pointer ke 7i2c_write(0x00); //mengatur nilai dari lokasi 7 ke 0i2c_stop(); //mengirim kondisi STOP

}

//******************************************************************void rtc_setTime(unsigned char h,unsigned char m, unsigned char s){

i2c_start(); //kirim kondisi STARTi2c_write(0xD0); //alamat DS1307 untuk ditulisi2c_write(0); //set register pointer ke 0i2c_write(s); //set detiki2c_write(m); //set meniti2c_write(h); //set jami2c_stop(); //kirim kondisi STOP

}

//********************************************************************void rtc_setDate(unsigned char y, unsigned char m, unsigned char d){

i2c_start(); //kirim kondisi STARTi2c_write(0xD0); //alamat DS1307 untuk ditulisi2c_write(0x04); //mengatur register pointer ke 4i2c_write(d); //mengatur harii2c_write(m); //mengatur bulani2c_write(y); //mengatur tahuni2c_stop(); //mengirim kondisi STOP

}

//********************************************************************void rtc_getTime(unsigned char *h, unsigned char *m, unsigned char *s){

i2c_start(); //mengirim kondisi STARTi2c_write(0xD0); //alamat DS1307 untuk ditulisi2c_write(0); //set register pointer ke 0i2c_stop(); //mengirim kondisi STOP

i2c_start(); //mengirim kondisi STARTi2c_write(0xD1); //alamat DS1307 untuk membaca*s = i2c_read(1); //baca detik, kemabali ACK*m = i2c_read(1); //baca menit, kemabali ACK*h = i2c_read(0); //baca jam, kembali NACKi2c_stop(); //kirim kondisi STOP

}

//*********************************************************************void rtc_getDate(unsigned char *y, unsigned char *m, unsigned char *d){

i2c_start(); //kirim kondisi STARTi2c_write(0xD0); //alamat DS1307 untuk ditulisi2c_write(0x04); //mengatur register pointer ke 4i2c_stop(); //mengirim kondisi STOP

Hal | 38

Page 39: I2C bus protocol

i2c_start(); //kirim kondisi STARTi2c_write(0xD1); //alamat DS1307 untuk dibaca*d = i2c_read(1); //baca hari, kembali ACK*m = i2c_read(1); //baca bulan, kembali ACK*y = i2c_read(0); //baca tahun. kembali NACKi2c_stop(); //mengirim kondisi STOP

}

int main(void){ unsigned char i,j,k;

rtc_init();rtc_setTime(0x19,0x45,0x30); //19:45:30 (hh:mm:ss)rtc_setDate(0x09,0x01,0x10); //09:01:10 (yy:mm:dd)usart_init();rtc_getTime(&i,&j,&k);usart_send_packedBCD(i);usart_send_packedBCD(j);usart_send_packedBCD(k);rtc_getDate(&i,&j,&k);usart_send_packedBCD(i);usart_send_packedBCD(j);usart_send_packedBCD(k);

while(1); //berhenti disinireturn 0;

}

Hal | 39