İnt32 lik sayıyı I2C ile gönderme sorunu

Başlatan enigmagazi, 09 Ağustos 2011, 14:08:41

enigmagazi

Arkadaşlar elimde int32 değerlikli bir sayı var bunu ben I2C veri yolundan başka bir pice gondermek istiyorum ama galiba tek seferde 8 bit gönderile biliyomuş bu sayıyı nasıl gonderip karşı taraftan bütün olarak tekrar nasıl alırım... 

GreeN

Daha önce i2c ile hiç çalışmadım. Ama 16 bit veriyi make8() fonksiyonunu kullanarak MSB ve LSB şeklinde ayırıp göndrebilirsiniz. Belki 32 veri içinde kullanabilirsiniz.

MSB ve LSB şeklinde başka bir yöntem;

int16 value; 
int8 val_high, val_low; 

value = 12345; 
val_low = (value & 0xFF) 
val_high = (value >> 8) & 0xFF;


Terörü Lanetliyoruz.

iyildirim

Bu sayıyı gösteren bir pointer tanımlayın. Ancak bunu char tipinde tanımlayın.
I2C ile bir byte gönderebiliyorsanız, zaten nasıl yapılacağınız biliyorsunuz demektir.

ilk byte olarak bu pointerin gösterdiği adres alanındaki byte'ı gönderin, sonrasında pointeri 1 arttırıp, tekrar  gönderin. 4 byte gidene kadar.

Alıcı picde de aynı şekilde gelen byteları INT32 bir sayının adresini gösteren char bir pointer kullanarak gelen byteları poniterin gösterdiği yere yazın.

Diğer bir yolda bu int32 sayı ile beraber 4 bytelık bir char arrayı union ile tanımlamak. Bu durumda da sırayla char array i göndermeniz yeterli.  Ancak bu durumda I2C ile gönderilecek sayıların hepsinin bu şekilde tanımlanması gerekli veya önce bu şekilde tanımlanmış bir sayıya atama yapıp öyle kullanacaksınız.


Tagli

Eğer imkanın varsa pointer casting yap. Yani 8 bitlik bir değişken pointer'ını int32'nin başlangıç adresi olarak belirle. Sonra da bir for döngüsü içinde bu pointer'ın içeriğini gönderip her seferinde 1 arttırırsın.

Kabaca şöyle birşey olur:
int32 gidecekSayi;
int8 *pointer = (int8*)(&gidecekSayi);
for (i = 0; i < 4; i++){
     i2c_gonder(*pointer);
     pointer++;
}


Not: Ben bu mesajı yazarken iyildirim benden önce davranıp durumu anlatmış. Ben de yalancı kodunu vermiş oldum. Bu şekilde CCS C'de çalışır mı onu bilemem.
Gökçe Tağlıoğlu

enigmagazi

make fonksiyonlarıyla 8 bite ayırdım bilgileri yalnız soyle bir sorun cıktı karşı tara gonderdikten sonra bunları nasıl ayrı ayrı değişkenlere ataya bilirim mesela
spı_write(1.değişken) spı_write(2.değişken)
diye I2C ile veri gonderiyorum karşıdada   
deg1=i2c_read();  deg2=i2c_read();
  diye okuma yapıyorum make16 ile birleştirip yazdırdığımda mesela
10000 değeri gonderdiğimde karşıda 10023 
8000  değeri gonderdiğimde karşıda 7967
5000 değeri gonderdiğimde karşıda  4883 değerlerini elde ediyorum oranlar sabit yuzdede kalsa okadr eklicm ama sürekli gonderilen sayının değerine göre eksilen sayı artıp azalıyo 20000 gonderdiğimde 200046 alıyorum bana bir fikir vere bilirmisiniz bu konuda neden boyle oluyor aca filtremi etmem lazım ediceksemde nasıl edicm...

GreeN

Verilerin bozuluyor. Normal for,while döngüleri içinde okumaya çalışırsan veriyi kaçırırsın. Okumayı interrupt ile yapın.


#int_ssp 
void ssp_isr(void) 
{ 

buffer[i] = spi_read(); 
i++; 

}

Terörü Lanetliyoruz.

enigmagazi

Alıntı yapılan: GreeN - 10 Ağustos 2011, 13:02:53
Verilerin bozuluyor. Normal for,while döngüleri içinde okumaya çalışırsan veriyi kaçırırsın. Okumayı interrupt ile yapın.


#int_ssp 
void ssp_isr(void) 
{ 

buffer[i] = spi_read(); 
i++; 

}




zaten oyle okuyorum

#INT_SSP 
void ssp_interrupt() 
{ 
incoming = i2c_read(); 
incoming1 = i2c_read();

x=make32(incoming1,incoming);
bu slave kısmım arda arda gonderip ard arda okuma yapıyorum ama baktığımda karşı tarafta en son gönderdiğim bit değeri iki değişkendede çıkıyo yani başta gönderdiğim yok ikiside aynı değeri alıyor...

Sepiroth

ayni interrupt icinde nie 2 kere okuyorsun ki? bence hata ordan kaynaklaniyor.
Either you feel it, or not...

enigmagazi

Alıntı yapılan: Sepiroth - 10 Ağustos 2011, 13:45:29
ayni interrupt icinde nie 2 kere okuyorsun ki? bence hata ordan kaynaklaniyor.

peki nasıl olması gerekiyo.

SpeedyX

i2c_read fonksiyonu 8-bit döndürüyor diyorsun ama make32 ile iki 16 bit i 32 bit e dönüştürüyorsun.
x=make32(incoming1,incoming);


1 - Interrupt içinde sadece tek okuma yap ve pointer/dizi ye yaz.
2 - Dizinin içeriğine bakarak kendin bunları 16bit yapmaya çalış, bakalım değerler mi hesap mı yanlış.
3 - Hazır fonksiyon kullanma, kaydırma komutlarıyla aynı işi yaparsın, yada union kullan.

enigmagazi

bunları birer örnekle göstermen mümkünmü mesela 1 madde de nasıl tek okumada iki 8 bitide okuya bilicem.

enigmagazi

proteusu adım adım çalıştırdığımda karşı tarafa değerler tam ulaşıyor sanırsam make16 fonksiyonuyla iki sekiz biti yüksek ve düşük değerlikli toplama yaptığım zaman yanlış işlem yapıyor hazır fonksiyon kullanmadan bunu nasıl yapa bilirim yani elimde 8 bit LSB 8 bi MSB var bunları nasıl yerli yerine toplarım...

Erol YILMAZ

yüksek seviyeli 8 biti 256 ile çarp ve bu sayıya düşük seviyeli 8 bit sayıyı topla.

enigmagazi

Gene make16 daki değerin aynısı cıktı anlamıyorum adım adım bakıldığında ik işlemciyide acıyorum masterde üretilen değer slave geliyo aynı sayıları alıyorum ama sonuc farklı acaba make8 işlemi yanlışmı yapıyor ben kendim 10 bitlik sayıda yuksek ve alcak değerlikli sayıları nasıl ayıra bilirim.

iyildirim

Alıntı yapılan: enigmagazi - 10 Ağustos 2011, 11:08:18
make fonksiyonlarıyla 8 bite ayırdım bilgileri yalnız soyle bir sorun cıktı karşı tara gonderdikten sonra bunları nasıl ayrı ayrı değişkenlere ataya bilirim mesela
spı_write(1.değişken) spı_write(2.değişken)
diye I2C ile veri gonderiyorum karşıdada   
deg1=i2c_read();  deg2=i2c_read();
  diye okuma yapıyorum make16 ile birleştirip yazdırdığımda mesela
10000 değeri gonderdiğimde karşıda 10023 
8000  değeri gonderdiğimde karşıda 7967
5000 değeri gonderdiğimde karşıda  4883 değerlerini elde ediyorum oranlar sabit yuzdede kalsa okadr eklicm ama sürekli gonderilen sayının değerine göre eksilen sayı artıp azalıyo 20000 gonderdiğimde 200046 alıyorum bana bir fikir vere bilirmisiniz bu konuda neden boyle oluyor aca filtremi etmem lazım ediceksemde nasıl edicm...


Bir karışıklık var.
Eğer bu fonksiyonların içerikleri değiştirilmedi ise SPI ile gönderip I2C ile almaya çalışılıyor gibi bir durum var. Önce ne kullanıldığına açıklık getirilmeli.

Ayrıca eğer gerçekten her iki tarafda I2C ise gönderme ile ilgili  kısım düzenlenmeli. Bu şekilde her seferinde adres ack-nack vs. tekrar gönderilir.
Gönderme sırasında adres +byte1 + byte2 + byte3 + byte4 şeklinde gönderilmesi daha mantıklı.  Diğer türlü herhangi bir veri kaybında alan taraf gelen byte'ın kaçıncı byte olduğunu nasıl anlayacak.

birleştirme işlemi için union da kullanabilirsiniz.
union longintchar { 
     int intvar ; 
     char charval[4]; 
     } ;
 longintchar var1;
 
 var1.charval[0] = gelenbyte1
 var1.charval[1] = gelenbyte2
 ...
 
 long var2 = var1.intvar;

gibi gelen byteları  arraya  yazıp numerik karşılıklarını alabilirsiniz.  her iki tarafda PIC olduğundan burada sorun yok. Başka bir device, işlemci vs. den okunduğunda little-bigendian durumuna da dikkat edilmeli.