I2C_kapak

I2C İletişim Protokolü ve MikroC Kütüphanesi

This post is also available in: English



  • Güncelleme 27.01.2019 Uygulamalar sırasında MCP4561 in çalışmasında sorun tespit ettim. Buna göre PIC in RB pinlerinde çalışmıyordu. Sonuç olarak bunun porttaki veri silinmesinden kaynaklandığını anladım.  Bunu gidermek için kodlara LAT sistemini ekledim. Dolayısı ile pin tanımlaması yapılırken fazladan “sbit I2C_SDA_VERI at LATB0_bit;” eklemesi yapılması gerekmektedir. ( LAT kısmı sabittir B0 – portb0 anlamına gelir.)
  • RTC (DS1307) kullanmam gereken bir projem için I2C protokolüne geçiş yaptım ancak PIC te yerleşik I2C modülü pinleri doluydu bu sebeple modüllerden bağımsız istenen pinde çalışabilen bir I2C protokolü ve kütüphanesi hazırladım.
  • Bu kütüphane ile PIC in herhangi 2 pin i kullanılarak iletişim kurulabilir.
  • I2C konusu anlatıldıktan sonra kütüphane kullanımı anlatılacaktır.

1- I2C Nedir ?

  • I2C 2 adet pin üzerinden iletişim kurmayı sağlayan bir yazılım protokolüdür.
  • Philips ( NXP ) firması tarafından oluşturulmuştur.
  • Bir entegre yada parça eğer içerisinde I2C sistemi var ise bu protokol ile kullanılabilir yani bir RAM entegresinde I2C yok ise bu protokol ile kullanılamaz.
  • I2C protokolünde yönetici MCU lara “master” yönetilen diğer parçalara ise “slave” denir.
Olumlu Yanları  Olumsuz Yanları
Esnektir, sistem içerisinde bir çok slave ve master/slave parça ekeleyerek istediğiniz gibi geliştirebilirsiniz.  Parça adresleri üretilirken tanımlandıkları için adres çakışması yaşanabilir
Adrese dayalı seçim yapar , yani fazladan bir CS ( chip select) pinine ihtiyacınız yoktur.  Diğer paralel iletişim sistemlerine göre hızları sınırlıdır
Bağlantı sadedir, birden fazla parçada kullansanız sadece 2 hat üzerinden bağlantı kurulur  Bazı durumlarda çok fazla pull-up direnci koymak PCB lerde alan sıkıntısına yol açabilir
Hata tespit sistemi olan ACK ve NACK bulunur. Böylece yapılan işlemin doğru olup olmadığı anlaşılır.(ileride anlatılacak)
Hız gözetmeksizin bu protokole sahip tüm parçalar ile çalışır

2- I2C Protokolünün Amacı

  • I2C protokolü normalde çok fazla pin ayrılması gereken parçaların sadece 2 adet pin kullanılarak sürülmesini amaçlar
  • I2C protokolünde sadece 2 pin ayrılarak aynı hat üzerine birçok RAM , EEPROM , RTC vb. parça bağlanıp kullanılabilir bu da fazladan pin ihtiyacını ortadan kaldırır.
  • I2C protokolünde hat üzerine başka MCU larda bağlanabilir bunlar gerekli zamanlarda hem master hem slave olarak yerini alabilir.

3- I2C Protokolü İçin Gerekli Yapının Oluşturulması

  • Temelde fazladan bir devreye gerek yoktur sadece SDA ve SCL uçları dirençler ile pull-up yapılırlar.
  • I2C protokolü  4 adet hız aralığına sahiptir.
    • 100 kbit/s
    • 400 kbit/s
    • 1 mbit/s,
    • 3,2 Mbit/s     hızlarında çalışabilir. Ancak kullanılan parçaların bu hızları desteklemesi gerekmektedir.
  • Kullanılacak dirençler için bir hesaplama yolu bulunsa da ben burada artık standartlaşmış değerleri vereceğim,  çünkü doğru hesap yapılabilmesi için I2C protokolüne bağlanacak parçalara giden bakır yolların dirençlerinin vs. hesaplanması gerekmektedir.
  • Aşağıdaki tablodan kullanılacak hıza uygun pull-up direnç değerleri seçilebilir
    Mod  Hız Direnç Aralığı
    Standart Mod 100 Khz 5kΩ – 10kΩ
    Hızlı Mod 400 Khz 2kΩ – 5kΩ
    Yüksek Hızlı Mod 3,4 Mhz 1kΩ
  • I2C protokolü için kullanılacak hattın da çok fazla uzun olmaması gerekmektedir. Bu iletişim protokolü kısa mesafe için uygundur.
I2C-protokolu-sistem
I2C protokolünün şematik olarak çalışma sistemi

4- I2C Protokolü Nasıl Çalışır ?

  • I2C protokolü temelde 4 adımdan oluşur bunlar
    • START  – İletişim başlangıç işareti
    • ADRES – İletişim kurulacak parçanın adresinin ve okuma-yazma yapılacağına dair işaret
    • DATA – Okunacak yada yazılacak veri trafiğinin başlatılması
    • STOP – İletişim durdurulması
    • İşlemlerden sonra gelen onay (ACK/NACK) kodu
  • Anlatımlarda “1” pin in yükseğe çekilmesi “0” ise aşağı çekilmesi demektir.

4A- I2C “START”  İletişim Başlangıç İşareti

  • İletişime başlanmadan önce mutlaka START işareti gönderilerek hatta bağlı olan tüm parçalar bekleme konumuna geçirilir.
  • START işareti için,
    • SCL=1       SDA=1  durumunda iken
    • SCL=1       SDA=0  yapılır böylece işaret gönderilmiş olur.
  • Dikkat edilmesi gereken nokta START işaretinden sonra iletişimin devamı için SDA=1 yapılacaktır ancak SDA=1 yapılmadan SCL=0 yapılmalıdır aksi halde SCL=1 iken SDA=1 yapılırsa hataya yol açar.
I2C-protokolu-start
I2C Protokolü START işaretinin gönderilmesi

4B- I2C Adres ve İşlem İşareti

  • Parçaların adresleri 7 bittir. Yapılacak işlemi belirten veri ise 1 bittir. Yani toplamda 8 bit (1byte) gönderilecektir.
  • Buna göre eğer
    • Yazma işlemi yapılacaksa  8. bit “0” olmalıdır.
    • Okuma işlemi yapılacaksa 8. bit “1” olmalıdır.
    • Örnek olarak adres 1001001 ise ve yazma yapılacaksa gönderilecek blok 10010010 olmalıdır
  • Adres gönderildikten sonra parçadan onay kodu olan ACK gelir. Bunu 4E maddesinde detaylı açıklayacağım
I2C-protokolu-adres
I2C Protokolünde ADRES 7 bittir.  8.bit ise yazma (0) yada okuma (1) yapılacağını bildirir.

4C – I2C “DATA”  Veri Transferi

  • Veriler 8 bit olarak gönderilirler.
  • Veri gönderilirken SDA ve SCL konumları aşağıdaki gibidir
    • SDA pinine veri yüklenmeden önce mutlaka SCL=0 yapılmalıdır.
    • SCL=0    SDA=1 veya 0 şeklinde(SDA gönderilecek bitlere göre ayarlanır)
    • SCL=1 yapıldığında SDA da yüklenen veri gönderilmiş olur.
    • Her veri gönderildikten sonra (8 bit gönderildiğinde) bize iletişimdeki parçadan onay kodu ACK gelir. Bunu 4E maddesinde detaylı açıklayacağım
  • Veri okunurken SDA ve SCL konumları aşağıdaki gibidir
    • Veri okumada yazmanın tersi olarak SCL=0 dan SCL=1 yapılır
    • Bu durumda SDA pinindeki veriler okunur.
    • Her veri okunduğunda ( 8 bit okunduğunda) eğer okumaya devam edeceksek parçaya kendimiz bir onay kodu ACK yollarız eğer okumak son bulacaksa o halde NACK  kodu göndeririz böylece parça okuma işleminin sona erdiğini belirtir.
I2C-protokolu-veri
I2C Protokolünde Veriler 8 bit olarak gönderilir ardından gelen 9. bit ise ACK/NACK verisini içerir.

4D- I2C “STOP” İletişim Durdurma İşareti

  • STOP durdurma işareti tüm iletişimi sona erdirir.
  • STOP işareti için
    • SCL=1      SDA=0 durumundan
    • SCL=1      SDA=1 durumuna geçildiğinde tüm iletişim sonlandırılır.
  • Yine burada dikkat etmemiz gereken nokta pull-up  yapıldığından dolayı SDA ve SCL daima 1 konumundadır. SDA=0 da SDA=1 yapmak için önce SDA=0 konumuna gelmeliyiz bu sebeple  SDA ayarlanmadan önce daima SCL=0 yapılmalı SDA pini sonradan ayarlanmalıdır.
I2C-protokolu-stop
I2C Protokolü STOP işaretinin gönderilmesi

4E- I2C Onay İşareti (ACK – NACK)

  • İletişim kuracağımız parçaya adres veya veri gönderdiğimizde bize onay kodu gönderir. Bu onay kodu ACK (acknowledge) olarak geçer tam terside NACK tır.
  • Bu onay geldiğinde SDA pin i normalde pull-up tan dolayı “1” durumunda iken “0” durumuna geçer böylece ACK onay kodu gelmiş olur.
  • Veri okumada ise tam tersi olarak okuma yaptıkça biz parçaya ACK göndererek okumanın devam edeceğini bildiririz. En son okuma biteceği zaman 9. bit i 0 yapmak yerine 1 olarak bırakırız böylece NACK gönderilmiş olur ve iletişim durdurulur.
  • Bu sebeple adres gönderildiğinde yada veri yazma yapıldığında daima 9. bit kontrol edilir eğer onay kodu gelmez ise tüm işlem iptal edilip yeniden START işareti gönderilerek iletişime yeniden başlanmalıdır.
  • Aşağıdaki grafikten tam bir veri iletişimini inceleyelim
I2C-protokolu-butun-iletisim
I2C Protokolünde bütün bir iletişim
  • Yukarıda görüldüğü gibi START işaretinden sonra 7 bit adres ve beraberinde yazma yapılacağını bildiren 8. bit gönderilmiş.
  • Bu durumdan sonra SCL ile clock gönderilmeye devam eder . 7 bit adres ve 1 bit işlem işaretinden sonra gönderilen clock ile iletişime geçtiğimiz parça SDA pinini sıfıra çekerek ACK yani onay gönderir. Onay  gelmez ise iletişim yenilenmelidir. Bu durumdan sonra gönderilecek yada okunacak tüm veriler başta adresi belirtilen parça ile yapılacaktır.
  • Adres parça tarafından onaylandı ve yazma yapacağımızı belirtmiştik. Şimdi 8 bit verimizi gönderiyoruz ve yine 9. bitte onay kodunu bekliyoruz parça yine SDA pinini sıfıra çekiyor ve veri yazmanın başarılı olduğunu onaylıyor.
  • NOT: Eğer yazma değilde okuma yaparsak ACK kodunu biz oluşturuyoruz yani 8 bit veriyi okuduktan sonra SDA pinini sıfıra çekiyoruz böylece okuma işlemi devam ediyor. Okuma biteceği zaman son okunan 8 bitin ardından bu sefer NACK gönderiyoruz yani SDA1 durumunda bırakıp sadece clock gönderiyoruz böylece parça okuma işleminin bittiğini anlıyor.
  • Ardından STOP işareti ile iletişim sonlandırılıyor. İstenirse arka arkaya durmaksızın veri yazılmaya devam edebilir bunda bir kısıtlama yoktur.
  • Yazma yaparken birden okuma yapmak istersek yine START işareti ile beraber aynı yolu takip ediyoruz.
  • Aşağıda osiloskopta gerçek bir iletişimi görebilirsiniz.
I2C-protokolu-osiloskop
I2C Protokolünün osiloskopta görüntüsü

I2C Protokolü Sonuç

  • I2C protkolü hakkında bilgi sahibi oldunuz. Yukarıdaki işleyiş genel bir iletişimi anlatmaktadır.
  • Her parçanın kendine has iletişim sistemi vardır yani bir I2C RAM e veri yazılacağı zaman kendi adresinden hariç birde verinin yazılacağı bölgenin adresi gönderilir kimi parçalarda direk yazılır içerisinde pointer her veri yazılışta kendiliğinden bir artar yani temel sistem aynı olmak ile beraber işleyişler farklı olabilir bunları parçaların data sheet lerinden bakarak öğrenmelisiniz.
  • Yeni eklenen bir özellik olarak bazı parçalar artık 10 bit adrese sahip olabilmektedir. Bunun da ayrıca bir gönderim yöntemi vardır ama bunu şu an kullanmadığım için ezbere eklemek istemedim . İleri ki projelerimde denk gelince gerekli güncellemeyi yapacağım ancak yine bu temel sistem geçerlidir, mevcut sistem ve kütüphane fonksiyonları ile bu işlem yapılabilmektedir fazladan bir eklemeye gerek duyulmamıştır.
  • Protokolü öğrendiğinize göre artık MikroC de yazdığım I2C Kütüphanesine geçebiliriz.

I2C MikroC Kütüphanesi

  • Bu kütüphane PIC18 lere uygun yazılmıştır. Çok ihtiyaç halinde PIC16 içinde dönüşüm yapılabilir.
  • Kütüphanenin amacı PIC in I2C modülünden bağımsız olarak istenen 2 dijital pin ile I2C işlemlerini yapmaktır.
  • Genelde I2C kütüphanelerinde START ve RESTART fonksiyonları bulunabilir bu kütüphanede START-BAŞLAT fonksiyonu her iki işlem içinde kullanılmaktadır.
  • PIC modülü kullanılan yazılımlarda iletişim hızı fonksiyon ile belirlenmektedir bunun amacı gerekli bekleme süresini PIC o modül içerisinde hesaplamaktadır ancak biz burada modülden bağımsız olduğumuz için gerekli hız ayarı kütüphane dosyası ile beraber verilen .h Header dosyası içerisinden ayarlanmaktadır.
  • Hız hesabı yapmak için ;
    • 1 khz = 1000 us
    • 100 khz = 10 us
    • 400 khz = 2,5 us  olmalıdır.
  • Şimdi fonksiyonları görelim

1- I2C Fonksiyonları

  • Fonksiyonlar tüm I2C  iletişim ihtiyacını karşılayacak temel fonksiyonlardır.Bunları kullanarak tüm I2C parçaları ile haberleşebilirsiniz.

 

 I2C_ILETISIM_BASLAT Fonksiyonu

Fonksiyon : void I2C_ILETISIM_BASLAT()

Amacı : I2C iletişimini başlatır aynı zamanda restart yerinede kullanılır

Parametreler : Bulunmuyor

Kullanım Şekli :

I2C_ILETISIM_BASLAT();//I2C iletişimini başlatır

Geri Bildirim : Void tipinde olduğundan geriye herhangi bir değer döndürmez

 

– I2C_ILETISIM_DURDUR Fonksiyonu

Fonksiyon : void I2C_ILETISIM_DURDUR()

Amacı : İletişimi sonlandırır

Parametre : Bulunmuyor

Kullanım Şekli :

void I2C_ILETISIM_DURDUR()//iletişimi her durumda sonlandırır

Geri Bildirim : Void tipinden olduğundan geriye herhangi bir değer döndürmez

 

– I2C_VERI_YAZ Fonksiyonu

Fonksiyon : unsigned char I2C_VERI_YAZ(unsigned char veri)

Amacı : Bağlantı kurulan parçaya 8bit veri gönderir

Parametre :

  • Veri : Gönderilecek 8bit veri bu parametreye yüklenir

Kullanım Şekli :

I2C_VERI_YAZ(0b01010101)//veri yazma ve iletişimdeki slave cihazın register adresleri bu fonksiyon ile yollanır

Geri Bildirim :

  • Geriye 1 değeri döndürüyorsa işlem başarılı demektir
  • Geriye 0 değeri döndürüyorsa işlem başarısız demektir

 

– I2C_VERI_OKU Fonksiyonu

Fonksiyon : unsigned char I2C_VERI_OKU(unsigned char sonlandir)

Amacı : Bağlantı kurulan parçadan 8 bit veri okur

Parametre :

  • sonlandir : Okuma yapılırken eğer okuma devam ediyorsa “sonlandır=0” (ACK) yapılır böylece parça okumanın devam edeceğini bilir ancak okuma sonlandırılacaksa son kez okuma yapılırken “sonlandir=1″(NACK) yapılarak okuma işlemi sonlandırılır.

Kullanım Şekli:

I2C_VERI_OKU(1);// bir kez okuma yapılır ve okuma işlemi sonlandırılır

Geri Bildirim:

  • Okunan 8 bitlik değeri geriye döndürür

 

– I2C_ADRES_GONDER Fonksiyonu

Fonksiyon : unsigned char I2C_ADRES_GONDER(unsigned char adres, unsigned char islem)

Amacı : İletişim kurulacak parçanın adresini gönderim bağlantıyı sağlar, ayrıca yapılacak işlemin yazma yada okuma olup olmadığını belirler

Parametre:

  • adres : bağlantı kurulacak parçanın 7 bit adresi yazılır. Bu adres parçanın data sheet inde yazmaktadır.
  • islem : Yapılacak işlemi belirler
    • işlem=0 ise yazma yapılacak demektir
    • işlem=1 ise okuma yapılacak demektir

Kullanım Şekli:

I2C_ADRES_GONDER(0b01101000,0);// 7 bit adres gönderildi ve yazma yapılacağı belirtildi
I2C_ADRES_GONDER(0b01101000,1);// 7 bit adres gönderildi ve okuma yapılacağı belirtildi

Geri Bildirim :

  • Geriye 1 değeri döndürüyorsa işlem başarılı demektir
  • Geriye 0 değeri döndürüyorsa işlem başarısız demektir

 

2- Fonksiyonların Uygulanması

  • Aşağıda DS1307 saat entegresi ile yapıtğım basit iletişim örneğini göreceksiniz. Ancak tekrar belirtmek gerekirse her parçanın iletişim kuralı ve sırası farklıdır bu sebeple bu kuralı ilgili parçanın data sheetinden öğrenmelisiniz.
  • I2C ile kullandığım her parça içinde ayrıca kütüphane yazıp yayınlayacağım

 

2A- Pin Tanımlamasının Yapılması

  • I2C için hangi pinleri kullanıyorsak bu kısımda onları belirtiyoruz
//I2C Pin Tanımlaması
 sbit I2C_SDA at RA5_bit;
 sbit I2C_SCL at RE0_bit;
 
 sbit I2C_SDA_VERI at LATA5_bit;//27.01.2019 güncellemesi ile eklendi
 sbit I2C_SDA_Direction at TRISA5_bit;
 sbit I2C_SCL_Direction at TRISE0_bit;

 

2B- İletişim Hızının Belirlenmesi

  • Bağlantı hızını .h header dosyasındaki ilgili yerden bekleme süresini arttırıp azaltarak ayarlıyoruz.
  • Genel olarak 100kHZ iletişim için 10 değeri uygundur.
#define I2C_ILETISIM_HIZI Delay_us(10);// iletişim hız ayarlaması

 

2C- I2C Örnek Çalışma

  • DS1307 entegresi için hazırladığım çok basit bir çalışma. En azından fikir vermek açısından faydalı olabilir
void  main()
{
    unsigned char veri[8];//okunan verilerin yazılması için oluşturulan dizi
    unsigned char txt[5];//okunan değeri GLCD de yazdırmak için çevrim işlemleri için oluşturuldu
    unsigned i =0;//onay kontrol koşulu için eklendi
    ADCON1=13;//PIC in A/D port ayarı
    CMCON=7;//comparatorler kapatıldı

    
    SAP1024_INIT (240,128,6);// sonuçları GLCD de görmek için eklendi


    I2C_ILETISIM_BASLAT();//iletişim başladı
    do{i=I2C_ADRES_GONDER(0b01101000,0);}while(i==0);//adres gönderilir ve onay gelip gelmediği denetlenir
    I2C_VERI_YAZ(0b00000000);//register seçiliyor//ds1307 registeri seçilir
    I2C_VERI_YAZ(0b10000000);//yazma işlemi yapılır
    I2C_VERI_YAZ(0b00000000);//yazma işlemi yapılır
    I2C_VERI_YAZ(0b00000000);//yazma işlemi yapılır
    I2C_VERI_YAZ(0b00000000);//yazma işlemi yapılır
    I2C_VERI_YAZ(0b00000000);//yazma işlemi yapılır
    I2C_VERI_YAZ(0b00000000);//yazma işlemi yapılır
    I2C_VERI_YAZ(0b00000000);//yazma işlemi yapılır
    I2C_ILETISIM_DURDUR();//iletişim durdurulur
    
    //iletişim tekrar başlatılır ve ds1307 aktif hale getirilir
    I2C_ILETISIM_BASLAT();
    I2C_ADRES_GONDER(0b01101000,0);
    I2C_VERI_YAZ(0b00000000);//register seçiliyor
    I2C_VERI_YAZ(0b00000000);
    I2C_ILETISIM_DURDUR();


  // Bu bölümde ds1307 den sürekli saniye verisi ham olarak okunur ve GLCD de yazdırılır
  while(1)
  
  {
    I2C_ILETISIM_BASLAT();
    I2C_ADRES_GONDER(0b01101000,0);
    I2C_VERI_YAZ(0b00000000);//register seçiliyor
    I2C_ILETISIM_DURDUR();
    
    I2C_ILETISIM_BASLAT();
    I2C_ADRES_GONDER(0b01101000,1);
    veri[0]=I2C_VERI_OKU(1);
    I2C_ILETISIM_DURDUR();
    
    ShortToStr(veri[0],txt);
    SAP1024_YAZI_YAZMA(1,1,txt);
    delay_ms(1000);
  }

}

 

Sonuç

  • Dersin sonuna geldik I2C kütüphanesi ile sizde kullanacağınız parçalar için kütüphane hazırlayabilirsiniz. Böylece işlemlerinizi daha kolay ve karmaşık hale gelmeden yapabilirsiniz.
  • Sorularınızı “Foruma” sorabilirsiniz.

Kütüphane Dosyaları

 


Yararlanılan Belgeler


 

ERCAN KOÇLAR Hakkında

Çalışmalarım çocukken başladı kolonyalı kağıtları yakmak, ilaçları birbirine katmak gibi değişik deneylerim vardı. Kimya kitabında elektroliz ile suyun hidrojen ve oksijene ayrıldığı ve hidrojenin yandığını yazıyordu, o zamanlarda aklım almıyordu sudan nasıl yanan....Devamını okumak için tıklayınız ;)