Devre:
Arduino Uno için SDA pini A4 nolu pindir, SCL pini ise A5
nolu pindir. Arduino Mega’da ise SDA ve SCL pinleri, 20 ve 21 nolu pinlerdir.
Slave’e gelen veriyi okuma:
Master’ın slave’den veri istemesi:
Slave’den master’a veri gönderme:
Master’ın gelen veriyi okuması:
Kodlar:
Arduino Uno ve Arduino Mega arasında yapılacak haberleşme
için bağlantı şeması:
I2C
Haberleşmesi:
I2C haberleşme
protokolü Philips tarafından geliştirilmiştir. Inter Integrated Circuit
kelimelerinin baş harflerinden oluşmaktadır. Düşük bant genişliğine sahip, kısa
mesafeli bir senkron haberleşme protokolüdür.
I2C protokolünde
haberleşme için iki hat kullanılır. Bunlar SCL ve SDA hatlarıdır. SCL (Serial
Clock) veri senkronizasyonunu sağlayan, clock sinyallerinin iletildiği hattır.
SDA (Serial Data) ise verilerin iletildiği hattır. SCL ve SDA hatlarına birer
pull-up direnci bağlanmalıdır.
I2C protokolünde,
aygıtlar master – slave ilişkisi içerisinde haberleşirler. Yani aygıtlar ya
master ya da slave olarak ayarlanmalıdırlar. Genellikle aygıtlardan biri master
diğerleri slave olarak ayarlanır. Ayrıca I2C protokolünün multimaster özelliği
de mevcuttur. Bu durumda hatta birden fazla master olabilir.
Haberleşme master
olarak seçilen aygıtın kontrolündedir. Haberleşmeyi başlatan ve bitiren
master’dır. Master SCL hattına clock sinyalleri göndererek haberleşmeyi kontrol
eder. Slave olarak seçilen ayıtlar clock sinyali üretmezler, yalnızca veri
alışverişinde bulunurlar. Her slave 7 veya 10 bitlik bir adrese sahiptir.
Master, slave’lere bu adresleri ile ulaşır. Master’ın bir adresi yoktur.
Master – slave
arasındaki veri alışverişi SDA hattı üzerinden gerçekleşir. Bu hatta veri
iletimi çift yönlüdür. Yani aygıtlara gelen ve giden veri tek hat üzerindedir. I2C
iletişimin veri yolu 8 bittir. Yani veriler 1 byte’lık bölümler halinde
iletilir.
Clock sinyali lojik-1
iken, data sinyali lojik-1’den lojik-0’a geçmesi ile start komutu verilir. Aynı
şekilde clock sinyali lojik-1 iken, data sinyalinin lojik-0’dan lojik-1’e
geçmesi ile de stop komutu oluşturulur. Veri iletimi start komutuyla başlar
stop komutuyla biter. Start – stop komutlarını master aygıt oluşturur. Master
aygıttan slave aygıta veri gönderme işleminde; ilk önce start biti, ardından
adres bitleri, ardından yazma/okama biti, daha sonra veri bitleri, en son
olarak da stop biti gönderilir. Her veri gönderiminde, 8 bit gönderildikten
sonra, slave aygıttan verileri aldığına dair onay biti olan ACK (acknowledge)
master’a gönderilir. Bazı durumlarda (veri iletiminde hata oluşması durumunda)
slave master’a ACK bitinin değili olan NACK bitini gönderir. Bu durumda master
aygıt stop biti göndererek haberleşmeyi durdurur, veya tekrar start biti
göndererek yeniden haberleşmeye başlar.
I2C haberleşmede her 9.
bit ACK veya NACK bitidir. Veri gönderiminde 8 bitlik bölümden sonra bu onay veya
onay değil biti gönderilir. I2C haberleşmede gönderilen R/W biti ise
okuma/yazma bitidir. Bu bit 0 ise yazma işleminin yapılacağını, 1 ise okuma ise
okuma işleminin yapılacağını bildirir.
Slave aygıt 7 bitlik
veya 10 bitlik adrese sahip olabilir. Slave 7 bit adrese sahip ise start
bitinden sonra bu 7 bit adres eklenir, ardından 8. bit olarak R/W (yazma/okuma)
biti eklenir. 9. bit ise ACK bitidir. Eğer slave 10 bit adrese sahip ise, adres
iki bölüm halinde gönderilir. İlk bölümde adres bilgisinin ilk iki biti yer
alır. Bu bölüm 11110XX(R/W) bitlerinden oluşur. Buradaki 11110 kısım sabittir.
XX kısmi ise adres bilgisinin ilk iki bitidir. 8. bit olarak ise R/W
(okuma/yazma) biti yer alır. Bu bölümün ardından 9. bit olarak ACK bilgisi
gönderilir. İkinci bölüm ise adres bilgisinin kalan 8 bitidir. Bu bölümün
ardından yine ACK bilgisi gönderilir. Ardından data bitlerinin iletilmesine
geçilir. Data bitlerinin gönderilmesinde de gönderilen her 8 bitlik bölümden
sonra ACK bilgisi iletilir.
Wire.h
Kütüphanesi
Arduino ile I2c
haberleşmesinde Wire.h kütüphanesini kullanmaktayız.bu kütüphanenin bazı
fonksiyonlarına kısaca değinecek olursak:
Wire.begin()
Haberleşmeyi
başlattığımız fonksiyondur. Haberleşmeyi master olarak başlatmak istiyorsak,
parametre girmeyiz. Eğer haberleşmeyi slave olarak başlatmak istiyorsak
parametre olarak adres bilgisi gireriz.
Wire.beginTransmission(adres)
Master aygıttan
adresini parametre olarak girdiğimiz slave aygıta veri gönderimini başlatmak
için bu ifadeyi kullanırız.
Wire.endTransmission()
Master aygıtın veri
gönderimini bitirmek için kullanılan fonksiyondur.
Wire.onReceive(işlem)
Master’dan slave’e veri
geldiğinde yapılacak olan işlemleri belirttiğimiz ifadedir. Parametre olarak
bir fonksiyon alır. Biz salave’e veri
geldiğinde ne yapmak istiyorsak bu fonksiyonda tanımlarız. Bu oluşturduğumuz
fonksiyon da parametre olarak integer bir parametre ile tanımlanmalıdır.
Wire.available()
Biz verilerin gelmeye
başladığını bu fonksiyon ile anlarız. Bu fonksiyon okunmamış (okunmayı
bekleyen) veri sayısını dönderir.
Wire.read()
Gelen veriyi okumak
için kullanılan fonksiyondur.
Wire.write()
Parametre olarak girilen
ifadeyi ileten ifadedir.
Wire.requestFrom()
Slave’lerden veri
istediğimiz ifadedir. Parametre olarak üç değer alır. İlk parametre veri
isteyeceğimiz slave’in adresidir. İkinci parametrede kaç byte’lık veri
istediğimizi bildiririz. Son parametresi ise boolean bir değişkendir.
Wire.onRequest()
Veri istendiğinde
slave’in ne yapacağını belirttiğimiz ifadedir. Parametre olarak bir fonksiyon
alır. Bu fonksiyonda neler yapılması gerektiğini tanımlarız.
Master’dan Slave’e Veri
Gönderme:
Wire.beginTransmission(4);
Wire.write(x);
Wire.endTransmission();
Wire.onReceive(receiveEvent);
void receiveEvent(int howMany)
{
int x = Wire.read();
}
Wire.requestFrom(2, 6);
Wire.onRequest(requestEvent);
void requestEvent()
{
Wire.write(x);
}
while(Wire.available())
{
int x = Wire.read();
}
- Master olarak seçilen arduino’nun kodları:
#include
<Wire.h>
char c;
void setup()
{
Wire.begin();
// haberleşme master olarak başlatıldı
Serial.begin(9600);
}
void loop()
{
Wire.requestFrom(1, 16); //Slave 1'den 16 byte'lık veri isteniyor
while(Wire.available()){
c = Wire.read();
Serial.print(c);
}
Serial.println();
Wire.beginTransmission(1); // Slave 1' veri gönderiliyor
Wire.write("Master: Merhaba"); // string veri gönderiliyor
Wire.endTransmission();
delay(500);
}
- Slave olarak seçilen arduinonun kodları:
#include <Wire.h>
char c;
void setup()
{
Wire.begin(1); // haberleşme slave 1 olarak başlatıldı
Wire.onRequest(requestEvent); // veri istendiğinde
Wire.onReceive(receiveEvent); // veri geldiğinde
Serial.begin(9600);
}
void loop()
{
delay(100);
}
void
receiveEvent(int howMany)
{
while(Wire.available()){
c = Wire.read();
Serial.print(c);
}
Serial.println();
}
void
requestEvent()
{
Wire.write("Slave 1: Merhaba");
}
void receiveEvent()
YanıtlaSilvoid requestEvent()
why you have not mentioned these two functions in loop?
sanırım sız 1 adet master ve 1 adet slawe olarak kodları verdınız. 1 master 2 slawe oldugu zaman master 1 ıncı yada 2 ncı slawe nası yoneticek? slawelere farklı bı ısımlendırme/tanımlama yapmamız gerekirmi?
YanıtlaSiluygulamada 1 adet slave olduğundan yalnızca ona isim verilmiştir. slave 1 olarak isimlendirilmiştir. birden fazla slave cihaz olduğunda her birine farklı isim vermek gerekecektir.
Silaynı adrese sahip birden fazla slave okuma hakkında bilginiz varmı?
YanıtlaSilaynı isme sahip birden fazla slave oluşturulabiliyor mu bilmiyorum. aynı isme sahip her iki slave de hatta aynı anda veri gönderdiğinde verilerde bozulma meydana gelebilir. o yüzden bu protokolde her bir slave ile tek tek iletişim kurulmaktadır.
Silbüyük data transferi yapılmak istendiğinde napılmı?
YanıtlaSildatalar bir buffer'da tutulup sonra iletilmelidir. yada ring buffer metodu kullanılabilir.
Silslave yalnızca char olarak mı okuyabilir? double gönderip double alamıyor muyuz? ya da char değil string diye okuyamıyor muyuz?
YanıtlaSil