ElectronX Lab

Arduino I2C xəbərləşməsi

Bu yazıda, I2C protokolu olan cihazlar arasındakı əlaqəni araşdıracağıq. Məsələn, iki arduino arasındakı xəbərləşməni həyata keçirdim.

Dövrə:

Dövrə

Arduino Uno üçün SDA pin A4 pinidir və SCL pin A5 pindir. Arduino Mega -da, SDA və SCL pinləri 20 və 21 -ci pinlərdir.

Arduino Uno və Arduino Mega arasındakı əlaqə üçün qoşulma diaqramı:

I2C Xəbərləşməsi:

I2C rabitə protokolu Philips tərəfindən hazırlanmışdır. Inter Integrated Circuit sözlərinin baş hərflərindən ibarətdir. Aşağı bant genişliyi, qısa diapazonlu sinxron rabitə protokoludur.

I2C protokolunda xəbərləşmə üçün iki xətt istifadə olunur. Bunlar SCL və SDA xətləridir. SCL (Serial Clock), məlumat sinxronizasiyasını təmin edən saat siqnallarının ötürüldüyü xətdir. SDA (Serial Data), məlumatların ötürüldüyü xətdir. SCL və SDA xətlərinə bir çəkmə rezistoru qoşulmalıdır.

I2C protokolunda cihazlar master-slave şəklindı xəbərləşmə qururlar. Yəni cihazlar ya usta (master), ya da fəhlə (slave) olaraq təyin edilməlidir. Adətən cihazlardan biri usta, digəri isə fəhlə olaraq təyin olunur. Bundan əlavə, I2C protokolunun multimaster xüsusiyyəti də mövcuddur. Bu vəziyyətdə birdən çox usta(master) da ola bilər.

Rabitə usta olaraq seçilmiş cihazın nəzarəti altındadır. Ünsiyyəti başlatan və bitirən ustadır. Usta SCL xəttinə saat siqnalları göndərərək xəbərləşməyə nəzarət edir.Fəhlə olaraq seçilən cihazlar saat siqnalları yaratmır, yalnız məlumat mübadiləsi aparırlar. Hər bir fəhlənin 7 və ya 10 bit ünvanı var. Usta fəhlələrə bu ünvanlarla çatır. Ustanın ünvanı yoxdur.

Master və slave arasında məlumat mübadiləsi SDA xətti üzərində baş verir. Bu xətt üzrə məlumatların ötürülməsi iki yönlüdür. Başqa sözlə, cihazlara gələn və gedən məlumatlar tək bir xətt üzərindədir. I2C rabitə yolu 8 bitdir. Yəni məlumatlar 1 baytlıq seqmentlərdə ötürülür.

Saat siqnalı(clock) məntiqi-1 olduğu halda, məlumat siqnalı(data) məntiq-1-dən məntiq-0-a keçəndə start əmri verilir. Eynilə, saat siqnalı məntiq-1 olduqda, məlumat siqnalı məntiq-0-dan məntiq-1-ə keçəndə dayan əmri yaranır. Məlumat ötürülməsi start əmri ilə başlayır və stop əmri ilə başa çatır. Əsas cihaz start -stop əmrlərini yaradır. Master cihazdan slave cihazına məlumat göndərilməsi prosesində; Əvvəlcə start (başlanğıc) biti, sonra ünvan bitləri, sonra yazma/oxuma biti, sonra məlumat bitləri və son olaraq stop biti göndərilir. Hər bir məlumat ötürülməsində, 8 bit göndərildikdən sonra, slave cihazdan məlumat aldığını təsdiq edən bit ACK (acknowledge) masterə göndərilir. Bəzi hallarda (məlumat ötürülməsi xətasında), qul ACK bitini deyil, NACK bitini masterə göndərir. Bu halda, ana cihaz bir stop biti göndərərək xəbərləşməni dayandırır və ya bir başlanğıc(start) biti göndərərək yenidən əlaqə qurmağa başlayır.

I2C xəbərləşməsində hər 9 -cu bit ACK və ya NACK bitidir. Məlumat ötürülməsində bu təsdiq və ya inkar biti 8 bitlik hissədən sonra göndərilir. I2C xəbərləşməsində göndərilən R/W biti oxuma/yazma bitidir. Bu bit 0 olarsa, yazma əməliyyatının, 1 olarsa oxuma əməliyyatının yerinə yetiriləcəyini göstərir.

Slave cihazı 7 bit və ya 10 bit ünvana sahib ola bilər. Slave-in 7 bitlik ünvanı varsa, bu 7 bitlik ünvan başlanğıc(start) bitindən sonra əlavə olunur, sonra R/W (yaz/oxu) biti 8-ci bit olaraq əlavə olunur. 9 -cu bit ACK bitidir. Slave-in 10 bitlik ünvanı varsa, ünvan iki hissəyə bölünür. Birinci hissə ünvan məlumatının ilk iki bitini ehtiva edir. Bu bölmə 11110XX (R/W) bitlərindən ibarətdir. Burada 11110 hissəsi sabitdir. XX qismi isə, bu ünvan məlumatının ilk iki bitidir. 8 -ci bit R/W (oxumaq/yazmaq) bitidir. Bu hissədən sonra ACK məlumatları 9 -cu bit olaraq göndərilir. İkinci hissə ünvan məlumatının qalan 8 bitidir. Bu hissədən sonra ACK məlumatları yenidən göndərilir. Sonra məlumat bitləri ötürülür. Məlumat bitlərini göndərərkən də ACK məlumatları hər 8 bitlik seqmentdən sonra ötürülür.

Wire.h Kitabxanası


Wire.h kitabxanasından Arduino ilə I2c xəbərləşmə üçün istifadə edirik. Bu kitabxananın bəzi funksiyalarına qısaca toxunsaq:

Wire.begin()

Xəbərləşməyə başlatdığımız funksiyadır. Xəbərləşməyə master olaraq başlamaq istəyiriksə, parametrləri daxil etmirik. Əlaqəyə slave olaraq başlamaq istəyiriksə, ünvan məlumatını parametr olaraq daxil edirik.

Wire.beginTransmission(adres)

Bu ifadədən, əsas cihazdan(master) ünvanını parametr olaraq daxil etdiyimiz slave cihazına məlumat göndərməyə başlamaq üçün istifadə edirik.

Wire.endTransmission()

Əsas cihazın məlumat ötürülməsini başa çatdırmaq üçün istifadə olunan funksiyadır.

Wire.onReceive (əməliyyat)

Masterdən Slave-ə məlumat alındıqda yerinə yetiriləcək əməliyyatları təyin etdiyimi ifadədir. Parametr olaraq bir funksiya alır. Verilər bu funksiyada Slave-ə məlumat gəldiyində nə etmək istədiyimizi müəyyənləşdiririk. Yaratdığımız bu funksiya da bir parametr olaraq bir integer parametri ilə təyin olunmalıdır.

Wire.available()

Bu funksiya ilə məlumatların gəlməyə başladığını başa düşürük. Bu funksiya oxunmamış (oxunmasını gözləyən) məlumatların sayını qaytarır.

Wire.read()

Gələn məlumatları oxumaq üçün istifadə olunan funksiyadır.

Wire.write()

Parametr olaraq daxil edilən ifadəni göndərən bir ifadədir.

Wire.requestFrom()

Slave-lərdən məlumat istədiyimiz ifadədədir. Parametr olaraq üç dəyər alır. Birinci parametr, məlumat istəyəcəyimiz slav-in ünvanıdır. İkinci parametrdə, neçə bayt məlumat istədiyimizi bəyan edirik. Son parametr boolean bir dəyişəndir.

Wire.onRequest()

Məlumat istədikdə slave-in nə edəcəyini təyin etdiyimiz ifadədir. Parametr olaraq bir funksiya alır. Bu funksiyada nə edilməli olduğunu müəyyənləşdiririk.

Master -dan Slave -a Məlumat Göndərmək:

Wire.beginTransmission(4);
Wire.write(x);
Wire.endTransmission();

Slave-ə gələn məlumatları oxumaq:

Wire.onReceive(receiveEvent);
void receiveEvent(int howMany)
{ 
  int x = Wire.read();
}

Master-in Slave-dən məlumat istəməsi:

Wire.requestFrom(2, 6);

Slave-dən Master-ə məlumat göndərmə:

Wire.onRequest(requestEvent);
void requestEvent()
{
  Wire.write(x);  
}

Masterin daxil olan məlumatları oxuması:

while(Wire.available())
{
  int x = Wire.read();
}  

Kodlar:

#include <Wire.h>

char c;

void setup()
{
  Wire.begin();  // Xəbərləşmə master olaraq başladıldı
  Serial.begin(9600);
}

void loop()
{
  Wire.requestFrom(1, 16);  //Slave 1'dən 16 byte'lıq məlumat istənilir
  while(Wire.available()){
    c = Wire.read();
    Serial.print(c);
  }
  Serial.println();
 
  Wire.beginTransmission(1);      // Slave 1' məlumat göndərilir
  Wire.write("Master: Merhaba");  // string məlumat göndərilir
  Wire.endTransmission();
 
  delay(500);
}
#include <Wire.h>

char c;

void setup()
{
  Wire.begin(1);  // xəbərləşmə slave 1 olaraq başladıldı
  Wire.onRequest(requestEvent);  // məlumat istənildikdə
  Wire.onReceive(receiveEvent);  // məlumat gəldikdə
  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: Salam");
}

Faylları yükləmək üçün vurun …

Yazının hazırlanmasında elektrikelektronikprojeleri.blogspot.com-dakı bənzər məqalədən istifadə edilmişdir.

Exit mobile version