This post is also available in: English

forum-banner


Konu ve mesaj oluşturabilmek için giriş yapmanız gerekmektedir.

I2C protokolü ile eeprom dan doğru verileri okuyamıyorum.

Sayfalar:1234
#include "I2C.c"

   sbit I2C_SDA at RC4_bit;
 sbit I2C_SCL at RC3_bit;

 sbit I2C_SDA_Direction at TRISC4_bit;
 sbit I2C_SCL_Direction at TRISC3_bit;
 
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
int i,k; //eepromdan okunan degeri tutacak olan deşiken
int deger;
char mesaj[7]; // dönüşüm icin gerekli olan karakter arrayı
int des;
char txt[5];
unsigned short a,b;
#define I2C_ILETISIM_HIZI Delay_us(10);// ı2c iletişim hız ayarlaması 10=100khz

void main(){
  ADCON0=0;
  ADCON1=7;
  cmcon=0x07;
  TRISB=0;
  PORTB=0;
  Lcd_Init(); 
  Lcd_Cmd(_LCD_CLEAR);               // LCD ekran temizlendi
  Lcd_Cmd(_LCD_CURSOR_OFF);          // cursor kapatıldı
  des=0;
  Lcd_Out(1,1,"Entegre Taraniyor");      
  Lcd_Out(2,1,"Adress :");


  while(1) {  
  while(des<=0)
  {
  for(k=0;k<=1024;k++)
  {
  I2C_ILETISIM_BASLAT();
  i=I2C_ADRES_GONDER(k,0);
  I2C_ILETISIM_DURDUR();
  if(i==1)
  {
  k=k*2;
  break;
  des=1;
  }
   }
   des=1;
   }


  IntToStr(k,mesaj);  // okunan değeri ekrana basmak icin ceviriyoruz.
  Lcd_Out(1,1,"Entegre Taraniyor");      
  Lcd_Out(2,1,"Adress :");
  Lcd_Out(2,10,mesaj);
  delay_ms(500);    // 0.5 saniye bekledikten sonra.
  Lcd_Cmd(_LCD_CLEAR);    // ekranı temizlettirdim.

}
}

I2C ile adress scanner yapmaya calıştım :) desimal olarak adresi verebiliyor. :)

hex formatı icin calışma yaptım normalde eeproom'un desimal olarak adresi 164

bu desimali hex formatını cevirince 0xA4 demesi gerekir ekranada A4 olarak basması gerekiyordu ama sadece 4 rakamını bastı A karakterini basmadı ona biraz uğraşacağım yine.

ama hala eepromu kullanabilmiş değilim dün gece bayağı calışmalarımda boş hücreleri 255 olarak okudum ama benim galiba verileri yazmamda sorun var.

Merhabalar

  • Yukarıda ki örnek eeprom için mi yoksa sadece deneme amaçlı mı ? Çünkü eeprom da adres şablonu bu şekilde değil.
  • Ayrıca işlemden sonra "k=k*2" ne için onu anlayamadım

İyi Çalışmalar

valla ben deneme yapmak istedim zaten data katoloğunda adress byte ına bakarak bunun adresini biliyorum. ben ayrietten. eppromun adres bitlerinden 4,2,1  bu bitten 2 ye karşılık gelen biti vcc hatıına bağlayarak adres atadım yani bunun adresi şu 1010010= bu 7 bit adres için son biti eklemedim (neden eklemedim söylüyeceğim ) okuma veya yazma.

bu ayarlar ile deneme yaptığımda bana adressin 82 olduğunu söyledi halbuki yanlış 82 değil 164 Olması gerekiyor ki 0xA4 ün decimal dönüşüm karşılığı 164 tür. bende fark ettimki yazma biti 0 olduğu icin ve onuda fonksiyon gönderdiği icin bizim forda bulunan adres 82 oluyor bu giderken dönüşümlerde son bite 0 eklenince 1 bit sol kayınca carpım işlemi görüyor ve entegreye 164 olarak gidiyor ama bizi kandıran nokta ekrana basma ve fonksiyondaki o işlemi unututmam dı. daha sonra bulduğu sonucu 2 ile carparak gercek değeri elde ettim. farkl şekilde adressledim yine adresi desimal cinsten doğru şekilde buldu. k=k*2; kodunun önemi buradaydı işte.

 

ben merak edip deneme amaclı yaptım illa eeprom değil başka birşey bağlanırsa onuda bulur diye tahmin ediyorum cünkü habire adress arttırıp gönderiyor ve entegrenin cevap verip vermediğine bakarak ya addresi buluyor veyada değeri 1 arttırıp tekrardan adress gönderiyor.

 

program başında fazladan değişkenler oluşuturulup kullanılmamıştır bunun nedeni programda bir sürü denemeler yaptım o yüzden silmeyi unutmuşum kullanılmayan değişkenler silinebilir.

Ercan hocama ayırca I2C_ADRES_GONDER(ADRESS,OKU VEYA YAZ); burada bir yanlışık var bu saat entegresinde nasıl calışmış cok şaşırdım. cünkü ben eepromu en son okumayınca ack gelip gelmediğine baktım ve gördüm ki entegreden onay gelmiyor. sonra incelediğimde adress kısmına 8 bit yazıldığını gördüm son okuma ve yazma biti peşine eklenince 9 bitlik bir gönderim oluyor. o yüzden entegre ile bir türlü haberleşme kuramamıştım daha sonra ilk biti silip deneyince do-while döngüsünden cıkmıştı yani entegre cevap vermişti iletişime.

 

şuanlık denemelerim sonucunda gördüklerim bunlar denemeye devam :))

Merhabalar

Ercan hocama ayırca I2C_ADRES_GONDER(ADRESS,OKU VEYA YAZ); burada bir yanlışık var bu saat entegresinde nasıl calışmış cok şaşırdım. cünkü ben eepromu en son okumayınca ack gelip gelmediğine baktım ve gördüm ki entegreden onay gelmiyor. sonra incelediğimde adress kısmına 8 bit yazıldığını gördüm son okuma ve yazma biti peşine eklenince 9 bitlik bir gönderim oluyor. o yüzden entegre ile bir türlü haberleşme kuramamıştım daha sonra ilk biti silip deneyince do-while döngüsünden cıkmıştı yani entegre cevap vermişti iletişime.

  • Burada bir hata yok. Fonksiyonda adres bilgisi ile sona gelen yazma yada okuma biti adres bilgisi kaydırılarak yine 8 bitlik yapılıyor. Bu kütüphane sadece DS1307 de değil önümüzdeki ay sonunda yayınlayacağım MCP4561 de de çalıştı. Çünkü I2C genel mantığı bu şekilde.
  • Eğer adresi yazarken okuma bitinide dahil ederek adres bölümüne yazdıysan o zaman o sebeple hata vermiş olabilir.
  • Yani yukarı gelecek olursak adres diyelimki "0b00001000" ve okuma yapacaz dedik yani "1" yazdık gidecek veri "0b00001001" bu şekilde düzenlenip gönderiliyor. Bit kaydırılarak.
  • Örnek olarak EEPROM adresi "1010010" ise bunu "01010010" olarak I2C fonksiyonuna yazmalısın yazmalısın. Eğer "10100100" yazarsan o zaman hata verir.
  • Yani yukarıda "k=k*2" yanlıştır. Çünkü k neyse adreste odur. Birleştirmeyi fonksiyon içerisinde yapmaktadır.
  • Eğer bu tarz sorunlar yaşadığından o kodlar ile beraber yazarsan daha fazla yardımcı olabilirim. Çünkü yaptığın silme işlemi ileride sorun yaratabilir yada kullanım hatasından kaynaklanabilir.
  • Ayrıca okumayı nasıl yaptın okuma prosedürü yazmadan biraz farklıdır sorun o da olabilir. Onuda yazabilirsen inceleyelim
  • Gerçek şartlarda deniyorsa SCL ve SDA pinini mutlaka 20k ile pull-up yapmayı unutma.
  • NOT: Bu tarz çalışmalarda gelen ve giden cevapları(ACK yada NACK gibi) osiloskop ile test ederek yayınlıyorum.

Ercan hocam K adresin kendisi olamaz eğer öyleyse hep yanlış bulur. mesela 82 buluyor Sadece K ya baktığımızda halbuki desimal olarak 164 olması lazım nezaman 2 ile carpıyorum ozaman doğru adresleri vermeye başlıyor.

K değeri vermesi lazım evet dediğiniz doğru benim k=k*2;  yapmanın nedeni ayrıca belirttiğimiz yazma bitinide göz önüne alarak hesaplatma sadece K nın ham değerine bakar isek hep yanlış adress okuruz diye düşünüyorum.

 

Notunuzu okudum işte bu yüzden  logic analyzeri aldım gelmesini sabırsızlıkla bekliyorum İsis'te hiç güzel olmuyor hiç olmassa logic analayzer ile programda nereyi atladığımı veya data katoloğundaki örnek okuma ile ilegili olan data transferini karşılaştırarak hatamı bulabilirim. ama yalnız ben data katoloğuna baktım nasıl okunması gerekip veya yazılması gerekttiğini aynısını yaptığım halde doğru sonuca ulaşamıyorum. belkide birşeyi atlıyorumdur.

Merhabalar

  • Zaten fonksiyon birleştirmeyi yapıyor yani k sadece adrestir :)
  • Evet mantık olarak şöyle I2C protokolünde tam bir adres verisi olsun diyorsak dediğin doğru adres+yazma biti bir bütün olarak geçiyor ancak EEPROM adresi demek kavram olarak pek mantıklı değil çünkü o birleşik değere adres dersek okuma yapacağımız zaman adres verisi hangisi olacak :) Okuma yapınca o zaman adres 169 mu diyeceğiz. Adres demek gerçek anlamda okuma ve yazma yapılan RAM gözlerinin adresidir. Bu gözlere yapılacak okuma-yazma işlemi adresten ayrıdır.
  • S 0 1 A2  A1  A0  R/W ACK
    • Yukarıdaki tabloya göre EEPROM adresi sadece kırmızı olan kısımdır. Sonraki yazma/okuma biti adrese dahil değildir. Cihazın adresi atıyorum
      • 1010111 olsun
        • okuma yaparsak bu 10101111 olur
        • yazma yaparsak bu 10101110 olur
        • Yani adres değişmez sadece yapılan işleme göre sonuna 1 yada 0 gelir.
        • Biraz daha işlevsel düşünürsek k=k*2 den adresi aldık diyelim ve ben bu adresi bulunca sonra buraya okuma yap dedim ve k değerini fonksiyona atadım. Bu halde birleşik veri gideceğinden hata verecek ve adres bulma işlemi aslında işe yaramamış olacaktır. Çünkü 168 verisinin sonuna bu sefer yine 1 ekleyecektir.
  • Evet çalışmalar için ufak test cihazları en iyisidir. Birde belki isisdeki eeprom eski olabilir bilemiyorum hiç kullanmadım en iyi gerçekte denemek.
  • Aslında sonda söylediğiniz kısmın kodlarını paylaşabilirsen üzerinden gidebiliriz . Yani okuma ve yazma ile ilgili kısmı.

İyi Çalışmalar

 

#include "I2C.c"

   sbit I2C_SDA at RC4_bit;
 sbit I2C_SCL at RC3_bit;

 sbit I2C_SDA_Direction at TRISC4_bit;
 sbit I2C_SCL_Direction at TRISC3_bit;
 
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
int i,k,t,g,h,j; //eepromdan okunan degeri tutacak olan deşiken
int deger;
char mesaj[7]; // dönüşüm icin gerekli olan karakter arrayı

#define I2C_ILETISIM_HIZI Delay_us(10);// ı2c iletişim hız ayarlaması 10=100khz

void main(){
  ADCON0=0;
  ADCON1=7;
  cmcon=0x07;
  TRISB=0;
  PORTB=0;
  Lcd_Init(); 
  Lcd_Cmd(_LCD_CLEAR);               // LCD ekran temizlendi
  Lcd_Cmd(_LCD_CURSOR_OFF);          // cursor kapatıldı
  I2C_ILETISIM_BASLAT();

                        // burda yazmaya başlıyorum.
       do{i=I2C_ADRES_GONDER(80,0); /* YAZMA YAPACAĞIM.*/}while(i==0); // eğer 0 gelirse iletişim başarısız demektir.
       do{k=I2C_VERI_YAZ(5); /*EEPROOMUN 5. HÜCRESİ SECİLDİ */}while(k==0); //  eğer 0 dönerse başarısız.
       do{t=I2C_VERI_YAZ(255); /*5.HÜCREYE 61 YAZILDI*/}while(t==0); // eğer 0 dönerse işlem başarısız.
       I2C_ILETISIM_DURDUR();  // Yazma bitti.
       
       Lcd_Out(1,1,"YAZMA TAMAM"); // yazmam tamam sa.
       delay_ms(3000);  // her ihtimale karşı 3 saniye bekliyeylim.
       Lcd_Cmd(_LCD_CLEAR);
       // bu kısımda'da okumaya geciyorum.
 I2C_ILETISIM_BASLAT();

       do{g=I2C_ADRES_GONDER(80,0); /* İŞLEM YAPACAĞIM */}while(g==0); // eğer 0 gelirse iletişim başarısız.
       do{h=I2C_VERI_YAZ(5); /* 5.HÜCREYİ OKUMAK İSTİYORUM */}while(h==0); //eğer 0 gelirse iletişim başarısız.
       I2C_ILETISIM_BASLAT(); // tekrardan start gönderilir.
       do{j=I2C_ADRES_GONDER(80,1); /* OKUMAYA GECİYORUM */}while(j==0); // eğer 0 gelirse iletişim başarısız.
       deger=I2C_VERI_OKU(1);
       I2C_ILETISIM_DURDUR(); // ILETISIM DURDUR STOP BİTİ GÖNDER.
       Lcd_Out(2,1,"OKUMA TAMAM");
       delay_ms(2000);
       Lcd_Cmd(_LCD_CLEAR);

  while(1) {  


  IntToStr(deger,mesaj);  // okunan değeri ekrana basmak icin ceviriyoruz.
  Lcd_Out(1,1,"ADRES YAZ OKU");
  Lcd_Out(2,1,"DEGER:");
  Lcd_Out(2,10,mesaj);  //2.satıra eeproomdan okuduğumuz değerleri yazdırdım.
  delay_ms(500);    // 0.5 saniye bekledikten sonra.
  Lcd_Cmd(_LCD_CLEAR);    // ekranı temizlettirdim.

}
}

Ercan Hocam kullandığım eeproom'un data katoloğu bu
-http://ww1.microchip.com/downloads/en/DeviceDoc/21202J.pdf

pdf te az cok ingilizcem le birşeyler anlasamda iletişim formlarına bakmak bile cok büyük bilgi veriyor. o yüzden iletişim dalga şekline bakarak kodumu yazdım.
fakat hala calışmış değil :))

buda benim devre şemam :))

 

http://hizliresim.com/PDOMjQ

 

100khz ve 400 khz calışabilir demiş ben 100khz icin ayar yaptım yani bunun calışması gerekiyor. ama işte ben nerde yanlış yapıyorum anlamıyorum.

Merhabalar

  I2C_ILETISIM_BASLAT();
  I2C_ADRES_GONDER(80,0);
  I2C_VERI_YAZ(5);
  I2C_ILETISIM_DURDUR();

  I2C_ILETISIM_BASLAT();
  I2C_ADRES_GONDER(80,1);
  deger=I2C_VERI_OKU(1);
  I2C_ILETISIM_DURDUR();
  • Okuma bölümünü yukarıdaki gibi yapabilirmisin birde böyle dene.
#define I2C_ILETISIM_HIZI Delay_us(10);// ı2c iletişim hız ayarlaması 10=100khz
  • Yukarıda ki kodu sil bunu zaten header dan okuması lazım
  • Bu kodlar PIC 18 lerde denendi isisdeki PIC i  PIC18f4620 yaparak dene
  • Birde eepromu illa PIC in scl sda sına bağlanaman gerek yok bu kütüphanenin bir özelliğide dilediğin porta bağlayıp çalıştırabilirsin.
  • Pull-up dirençleri de 20 k yapmalısın.
  • Bunları tek tek denersen sorunu bulabilirsin.
  • NOT: Bu 127 hatası benimde başıma geldi sonra pull-up ları 20 k yapınca düzeldi ancak isiste ne kadar geçerlidir bilemiyorum önce bunu dene bence.

Ercan hocam pull-up ları 20 k yaparak 877a denedim yine aynı. sonra sizin verdiğin kod bloğu ile değiştirdim okuma bloğunu tekrar denedim tekrar aynı.

sonra 18f4620 ye gectim pull-up lar 20K denedim yine aynı 127 değerini gösteriyor. kafayı yedirtcek bana :))

 

evet sda ve scl yi istediğim yere bağlayabilirim biliyorum hocam, sadece her şey garanti olsun diye ne olur ne olmaz oraya bağladım :D  napıcaz hocam nasıl gecicez burayı.

Merhaba

SDA ve SCL yi başka portlara bağlayarak dene .

Bence sorun isisteki parçada. I2C de SCK olmaz SCL olur. Ama isis te SCK gözüküyor. Onu da kontrol et bence.

Eepromun vdd ve vss uçlarıda yok onlar bağlanmıyor mu isiste.

Bence sen çinden bu eepromdan da al pahalı değildir gerçekte dene isiste doğru bildiğinide unutursun. :-)

Denemeye devam :)

Sayfalar:1234