I2C, Slave PIC'ten Okuma Nasıl yapılır?

Başlatan RcALTIN, 04 Nisan 2010, 00:45:58

RcALTIN

Merhabalar, bir süredir tasarlamayı düşündüğüm bir devre var. Bu devrede bir PIC üzerinde(master) yalnızca lcd ve tuş takımı bulunacak, bu PIC diğer PIC'lerin(slave) portlarını yönetmem için bir nevi arayüz görevi görecek. Bugün bu devreyi hayata geçirmek için, i2c hakkında biraz araştırma yaptım. CCS ile kodları oluşturup, Proteusta testler gerçekleştirdim ve sonuç olarak i2c kullanarak master PIC'ten, istediğim herhangi bir slave PIC'e veri göndermeyi de başardım(örnek kodlar aşağıda)... Ancak zaman zaman slave piclerdende veri almam gerekecek, slave PIC'lerden veri okuma işini nasıl gerçekleştireceğim?

master için #use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3) şeklindeki tanımlamadan sonra, veri göndermek için:
i2c_start();
delay_ms(50);
i2c_write(0xb0);//slave adresi
delay_ms(50);
i2c_write(1);//veri
delay_ms(50);
i2c_stop();


slave için #use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0xb0) tanımlamasından sonra:
#int_SSP
void  SSP_isr(void) 
{
   d2 = i2c_read();
   delay_ms( 100 );
   d1 = i2c_read(); 
   delay_ms( 100 );
   output_high(PIN_B6);
   delay_ms(100);
   output_low(PIN_B6);
}

void main()
{
    while(1)
   {
      if(d1==1)
      {
         output_high(PIN_B4);
         delay_ms(500);
         d1=0;
         
      }
      output_low(PIN_B4);
   }
}   


KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

RcALTIN

#1
Bu konu üzerinde bir süre çalışıp ilerleme kaydetmiştim. Aşağıdaki paylaştığım kodlarla istediğim Master-Slave iletişimi sağladım ancak işin içine 2. başka bir slave aygıt girince -proteusta- sapıtıyor. İlk işlem olarak okuma veya yazmayı bir slave pic'e yaparsam, farklı adresli bir slave aygıt ile işlem kurana kadar bir sorun çıkmıyor; ancak farklı adresli bir slave erişmeye çalıştığım anda slave pic'lerin hepsi hattan düşüyor, artık "ACK" vermiyorlar. Oysa slave picler ACK vermezlerken DS1621ler v.s diğer slave aygıtlar ile iletişimde bir sıkıntı yok...
Şimdi bu duruma göre sorunumuz slave pic için yazılan kodlarda gibi görünüyor, ancak bazı üyeler devrenin proteusta sorun çıkarsada gerçekte çalışabileceğini söylemişti, denemek isteyen olursa:

18f452 master için:
#use i2c(MASTER, sda=PIN_C4,scl=PIN_C3,force_hw)

'dan sonra
BOOLEAN slave_hazir(BYTE adres) 
{
   BOOLEAN ack;
   i2c_start();
   ack = i2c_write(adres);
   i2c_stop();
   return !ack;
}

void slave_yaz(BYTE adres, BYTE tampon_adresi, BYTE veri) 
{
   while(!slave_hazir(adres) && deneme < 5)
   {
      deneme++;
   }
   i2c_start();
   i2c_write(adres);
   i2c_write(tampon_adresi);
   i2c_write(veri);
   i2c_stop();
}

BYTE slave_oku(BYTE adres, BYTE tampon_adresi) 
{
   BYTE veri;
   while(!slave_hazir(adres) && deneme < 5)
   {
      deneme++;
   }
   i2c_start();
   i2c_write(adres);
   i2c_write(tampon_adresi);
   i2c_start();
   i2c_write(adres+1);
   veri = i2c_read(0);
   i2c_stop();
   return(veri);
}

metodları ile, slave'e yazmak için
slave_yaz(slave_adres,eeprom_adres,veri);

slave'den okumak için
veri = slave_oku(slave_adres,eeprom_adres);


16f877 slaveler için ise her biri farklı adresli olmak üzere(0x8C,0x8E gibi):
#use i2c(SLAVE,sda=PIN_C4,scl=PIN_C3,address=0x8E,force_hw)
BYTE adres;

tanımlandıktan sonra:
#int_SSP
void  SSP_isr(void) 
{
   state = i2c_isr_state();
   if(state == 0x80)
   {
      i2c_write(read_eeprom(adres));
   }
   else if(state > 0)
   {
      incoming = i2c_read();
      if(state == 1)
      {
         adres = incoming;
      }
      if(state == 2)
      {
         write_eeprom(adres,incoming);
      }
   }
}


kesmesiyle isteğe göre master'dan geleni eeproma yazıyoruz veya eepromdan okuyup mastera yolluyoruz ancak gel gelelim yukarıda bahsettiğim sorunu aşamıyoruz...
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

bbs2006

size bu konuda bir sorum olacaktı. ben
0xc2 adresine   0x8e bunu yüksek byte      0x00 da düşük bayte yazmak istiyorum. bunu ccs c nasıl yazabiliriz. yardımcı olursanız sevinirim.

RcALTIN

#3
Alıntı yapılan: bbs2006 - 26 Temmuz 2010, 23:18:41
size bu konuda bir sorum olacaktı. ben
0xc2 adresine   0x8e bunu yüksek byte      0x00 da düşük bayte yazmak istiyorum. bunu ccs c nasıl yazabiliriz. yardımcı olursanız sevinirim.

Şimdi benim bildiğim, daha doğrusu ccs'in i2c örneklerinden anladığım kadarıyla master'in talebi doğrultusunda her seferinde 1 byte gönderir veya alabilirsin. şimdi 0xc2 adres ama ne adresi? slave aygıt adresi ise, yukarıdaki kodlara göre örneklersek slave_yaz(0xc2,0x00,0x00) ve sonra slave_yaz(0xc2,0x01,0x8e) şeklinde slave pic içerisindeki tampona bu bilgiyi 2 byte olarak yazarsın, gerektiğinde aynı 2 tampon adresinden okuyup birleştirirsin.(yukarıdaki slave pic aynı zamanda eeprom emulatörü olduğundan, eepromlarda da böyle yapılabilir) Eğer yanlış anlamadıysam durum böyle...
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

bbs2006

Burada pic ile sp5055 diye bir entegre var. burada c2 sp5055 adresidir. buraya bilgiyi yazacaz.

RcALTIN

ilginç bir şekilde internettte bu entegreyle alakalı hiç  bir örnek yok gibi, oysa bu forumda da bu entegreyi kullanan onlarca kişi mevcut. sp5055'in datasheetini inceledim, alttaki tabloyu yorumlamamız gerekiyor önce...



P3 pinini gnd bağlarsak adres 11000000(0xC0) oluyor. Yani bir bilgi yazmak için adresi 0xC0, okumak için adresi 0xC1 yazmamız gerekiyor. Daha sonraki rogrammable divider satırında bulunan 2^n ler sanırım frekansı oluşturan değerlerin parçalanmış halleri, matematiğim pek iyi değildir o nedenle yorumlayamıyorum. Ayrıca bu tabloyu da, benim yukarıdaki sorunumu da çözebilecek en az 50 kişi vardır bu forumda ama neden yardımcı olmamak için direniyorlar anlamıyorum...
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

bbs2006

Yardımlarınız için teşekkür ederim. aynen düşüncelerine katılıyorum. picbasic te oldugu gibi direk olarak ccs c de yapamıyoruz. ı2c komutunu kullanarak. bir şekilde yapılabilir.ancak denemek lazım diye düşünüyorum.

RcALTIN

Alıntı yapılan: bbs2006 - 29 Temmuz 2010, 19:56:02
Yardımlarınız için teşekkür ederim. aynen düşüncelerine katılıyorum. picbasic te oldugu gibi direk olarak ccs c de yapamıyoruz. ı2c komutunu kullanarak. bir şekilde yapılabilir.ancak denemek lazım diye düşünüyorum.

Sorun derleyici de değil ki, sizin şuan ki sorununuz frekansın hangi mantıkla "2 byte" olarak ayrıldığıdır, yoksa ccs veya picbasic tek farkeden komutun yazım farklılığı; o da şöyleki picbasicde tek satırda "i2cwrite sda,scl,adres,[a,b,c,d]" (yazımda ufak hatalar olabilir) şeklinde slave node'a veri yazıyorsak, ccs de "i2c_start(); i2c_write(adres); i2c_write(a);  i2c_write(b); i2c_write(c);"(belki tek satırda yazma imkanı mevcuttur overload edilerek) şeklinde parçalayarak aynı işi yapıyoruz. Neyse umarım sp5055'i nasıl kullanacağınızı bir şekilde öğrenirsiniz, benim ilk mesajda belirttiğim sorun ile sizin uğraştığınız konunuz farklı şeyler gibi görünüyor...
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !