avatar_Mayhoş

Picler Arası i2C Haberleşme

Başlatan Mayhoş, 09 Ocak 2020, 14:24:35

Mayhoş

Arkadaşlar merhaba,

Parça parça yapmaya çalıştığım devreyi tamamlamak üzereyim. Açtığım konulara bakanlar ve hatırlayanlar bilir ki çok kısa sürelerde çalışma yapmaktayım.

Sizlere şöyle bir sorum olacak. Fikir alışverişine çok ihtiyacım var.

1 master ve 12 tane slave'im olacak.

Ama bu slaveler aynı anda 2'li şekilde çalışacak. Yani masterdan bir bilgi gönderdiğimde 1. ve 2. slave'im bu bilgiyi aynı anda almalı ve ona göre bir işlem yaptıracağım. Mikrosaniyelerde çalışıyorum. 1us'lik bir kayma çok önemli değil ama ne kadar senkron olursa o kadar doğru ve kararlı olur.

Soruma gelecek olursam. Şimdi master pic'i aynı zamanda plc'ye bilgi göndermek için kullanıyorum. RX ve TX ile rs485 haberleşmesi yapıyorum.

Master ile slave picler arası i2C ile haberleşiyorum şuanda. SCL ve SDA ile.

Ama bu i2C konusunda çok yeniyim. Bu haberleşme ile slave cihazlara istediğim şekilde aynı anda veri gönderebiliyor muyum?

i2c_start();
i2c_write(slave1_adres);
i2c_write(data);
i2c_stop;

i2c_start();
i2c_write(slave2_adres);
i2c_write(data);
i2c_stop;

Mesela bu şekilde 2 slave'e aynı bilgiyi gönderiyorum ama aynı anda gitmiyordur tabi kod işleme süresinide göz önünde bulundurursak.

i2c_start();
i2c_write(slave1_adres);
i2c_write(slave2_adres);
i2c_write(data);
i2c_stop;

Bu formatta da yazınca 2.slave işlem yapmıyor. Tabi i2C formunu bozuyorum muhtemelen.
Slave'ler aynı bilgiyi alacak ama farklı işlemler yapıp farklı cevaplar verecekler.

Aynı data da olsa illa ayrı ayrı mı yazmak gerekiyor slave cihazlara?

Ya da tavsiye edeceğiniz başka bir metod var mıdır?

ete

I2C konusunda bilgi eksikliğin var. I2C sistemi büyük ölçüde haberleşmede adresleme mantığına dayanır.
Master hatta bir bilgi yolladığında bu hatta bağlı olan 2 slave ünitenin her birinin ayrı adresi olmak zorundadır. Aksi halde işler karışır. Çünki bu sistemde master bir bilgi yollar slave bilgiyi alır ve ACK denilen bir yöntem ile aldığını belli eder. Bunu yanlızca alan ünite yapmalı diğeri sessiz beklemelidir.
Bu sebeplerden dolayı I2C sistemi ile çalışan aletlerin tamamının bir device adresi bulunur. Bu adresin son bir kaç biti ise slave adreslemesinde kullanılır. Olayı daha iyi anlaman için I2C eprom data sheetlerini incele istersen.

Kolaylıkla anlaşılacağı üzere aynı bilgi yollansa bile her slave için aynı bilgi farklı adresli olarak yeniden yollanmalı. Bunu sistemin özelliklerini düşünerek söylüyorum. Picleri I2C ile haberleşerek kullanmak pek avantajlı olmayacak bana kalırsa. SPI kullansan belkide daha doğru olur. Pin sıkıntısı var ise sözümü geri alırım. Diyeceğim odur ki I2C ile birden fazla Pic haberleştirmek pek kullanılan bir yöntem değil. Bu nedenle benim ve diğer arkadaşların bu konuda tecrübe eksikliği var yada vardır. Bu nedenle birazda deneyerek bu işi kotarmak zorundasın sanırım.
Slave lere farklı adres bilgisi vererek işe başla. Master kime bilgi yollayacak ise ona ait adresi kullansın. Alanda aynı adresi kullanarak alsın.

Ete

MB_77

#2
bu mesaj tarafımdan silinmiştir.

Mayhoş

#3
Merhaba,

i2C haberleşme ilgili bir sorum daha olacaktı.

Masterdan slave'e for döngüsüyle 1-2-3-4-5-6-7...16 bilgisi yolluyorum sırayla.

Bunu alan slave ile her bir bilgide bir sensörü çalıştırıyorum.

1 bilgisi sonucu sensör(1)=1 ya da sensör(1)=0 durumuna bakıyorum.
2 bilgisi sonucu sensör(2)=1 ya da sensör(2)=0 durumuna bakıyorum.

Böyle 16 sensörüde sırayla kontrol ediyorum.
En son slave'den master'a tek bir cevap göndermem gerekiyor. Bu cevapta 16 sensörün durumu.

Yani 16 sensör için 65535 sayısına kadar bir değerim oluyor.

sensör(1) + sensör(2)*2 + sensör(3)*4 + sensör(4)*5 .... sensör(16)*32768 = sensör durumu

Şeklinde bir işlem yaptırıp mastera göndereceğim ve master tarafında tek bir cevap ile 16 sensörün durumunu anlayabileceğim

Örneğin sayım 65535 ise = 1111111111111111 olduğunu bilirim.
örneğin sayım 16 ise = 0000000000010000 olduğunu bilirim.

Fakat sorum şu; i2C'de sanırım 8bitlik data iletilebiliyor. Bunu iletemeyeceğim demektir galiba bu.

Peki 16bitlik bu veriyi iletmenin başka nasıl bir yolu vardır?

Ya da yanlış yoldamıyım başka bir şekilde mi sensör durumlarını göndermem gerekir?
Tek seferde bu 16 sensörün durumunu hangi mantıkla i2C üzerinden master'a gönderebilirim?

ete

Normal şartlarda I2C şayet WOrd değişkeni kullanıp gönderme kısmına o değişkeni yazarsan 16 biti tek seferde gönderir. BU yalnızca değişken sorunudur. Ama derleyyiciden derleyiciye değişebilecek bir durum sanki.
Derleyicide komut açıklamasına bakmalısın.

Ete


Mayhoş

#5
CCS C'de şu tanımlama ile tanıtıyorum sayımı.

unsigned long

Long veri türü 16 bit değerinde tamsayıları hafızada tutmaya yarayan veri türüdür. 16 bitlik tamsayı değeri -32767 ile +32767 arası değerlerdir. Eğer değişken tanımlarken önüne unsigned (işaretsiz) komutu getirilirse 0 ila +65535 arasındaki tamsayıları hafızada tutabilme özelliğine sahiptir.



Şöyle bir mesaj yapısı görmüştüm o yüzden kafam karışmıştı. Yani benim değişkenim böyle ise bunu aynen gönderecektir değil mi?

Teşekkürler.

ete

Demiştim ya derleyicinin özelliğidir diye bak Basic derleyicisi bu konuda ne diyor;
" If a word-sized Value is specified, 2 bytes are sent, high byte first, followed by the low byte. This order is different than the way variables are normally stored, low byte first."
Şunu diyor, Şayet Word (16bit) değişken kullanılır ise, 2 byte yollanır. Önce HIGH byte daha sonrada LOW byte şeklinde.
Benzer açıklamayı Adress değişkeni içinde kullanmış. Şayet 16 bitlik adres değişkeni kullanırsanız, 16 bitlik adres yollanır, şayet 8 bitlik adres kullanırsanız 8 bit adres yollanır şeklinde. Nasıl bir adres kullanılacağı ise bağlantı kurduğunuz elemanın hafıza yapısı ile alakalıdır. 16 bitlik bir adrese sahipp hafıza var ise (I2C_epromlar) o zaman 16 bit kullanmak gerekir. Değilse 8 bitlik yeterli olacaktır.

Verdiğin açıklama şayet CCS dökümanlarından alınma ise bir defa şundan emin olabiliyoruz. Değişkenin Word olursa (Sende LONG denilmiş benim bildiğim LONG 32 bitlik değişkeni ifade eder ama neyse) gönderi her şekilde 2 byte ayrı ayrı yollanacak şekilde düzenleniyor demektir.
Burada önemli olan 16 bitlik değişkende hangi byte'ın önce yollanacağıdır. Daima HIGH byte önce yollanmalıdır. Buda I2C nin genel kuralıdır.

Ete

Mayhoş

#7
Cevap için teşekkürler.

CCS C'de işler biraz zorlaşıyor sanırım. Belki bende zorlaştırıyor olabilirim emin değilim.

Şöyle bir çözüm yaptım. Paylaşayım. Belki ihtiyacı olan birileri daha çıkar.

Slave'den mastera 16 bitlik data göndermem gerekiyordu.
2 tane 8 bitlik data şeklinde gönderdim.

Bunun için önce masterdan slave'e bir mesaj yolladım. Slave bu mesajı alınca datanın ilk 8'ini gönderdi.
Daha sonra masterdan slave'e başka bir mesaj daha yolladım. Slave bu mesajı alınca datanın son 8'ini gönderdi.

Mastera gelen bu dataları A ve B değişkenlerine atadım.
Daha sonra make16(B,A) komutu ile birleştirip 16 bit yaptım.

Eminim çok daha pratik kolay bir yolu vardır i2c haberleşme üzerinden 16 biti göndermek için ama ccs c'de çözemedim olayı. Bu şekilde bir çözüm ile halletmek durumunda kaldım.

Tekrar teşekkürler.

ete

Daha pratik yolu önceden de söyediğim gibi yalnızca A yollamak yerine A ve B yi birlikte arka arkaya yollamak olur. Böylece ikinci bir alver işlemi gerekmez.

Ete

Mayhoş

#9
Alıntı yapılan: ete - 28 Ocak 2020, 16:21:51Daha pratik yolu önceden de söyediğim gibi yalnızca A yollamak yerine A ve B yi birlikte arka arkaya yollamak olur. Böylece ikinci bir alver işlemi gerekmez.

Ete

Biliyorum CCS C ile çok aranız yok ama mantık aynıdır diye düşünerek soruyorum,

CCS'de A ve B'yi ayrı ayrı yolluyordum ve simülasyonda da i2C ile baktığımda ayrı ayrı cevap görüyordum.

Örneğin:

S 13 A 04 N p
S 13 A 08 N p

gibi. Sizin dediğin şekilde A ve B yi birlikte arka arkaya göndermek için şöyle bir şey yaptım.

Slave'den:

i2c_write(A);
i2c_write(B);

Normalde bir koşula bağlıyordum. Master okumak isteyince bir mesaj yolluyordu tek tek slave'den cevap veriyordum.
Master tarafında da tek tek okuyordum tabi. Şimdi master tarafında da arka arkaya okumak gerekir diye düşündüm.

Şöyle yazdım Master'a:

i2c_start();
i2c_write(Slave);
A=i2c_read(0);
B=i2c_read(0);
i2c_stop();

Gelen cevap bu şekilde oldu: S 13 A 04 N FF N p

Tek tek koşula bağlayıp gönderdiğimde ve tek tek okuduğumda ayrı cevaplarda sorun yoktu. Ama birleşince diğer bilgi FF görünüyor. Master'ın okuma kısmında hata yaptığımı düşünüyorum. Okurken araya bekleme de koydum işe yaramadı. Yapısal bir hata var sanırım.

--

Düzenleme: CCS kullananlar için yardımı olur belki.

Slave'den 2 tane 8 bitlik mesajı peşpeşe göndermek için aşağıdaki gibi kullanım yapılabiliyormuş.
if(state >= 0x80)
{
if(state==0x80)
i2c_write(A);
if(state==0x81)
i2c_wrie(B);
}

Master'dan okumak içinde aşağıdaki gibi.
i2c_start();
i2c_write(slave);
A=i2c_read();
B=i2c_read(0);

Buradaki (0) kısmı mesajın sonunu ifade ediyormuş. O yüzden okuma işleminde tüm okuma komutları bittikten sonra en sonuncusuna yazmak gerekiyormuş. Benim anladığım kadarıyla böyle. Bu şekilde Master-Slave arası istenildiği gibi data gönderilip alınabiliyor test ettim.

Teşekkürler.

Powered by EzPortal