i2c ile haberleşme

Başlatan cemilsivas, 09 Mart 2020, 23:59:18

cemilsivas

İyi akşamlar arkadaşlar. Arabamdaki bilgi ekranıyla i2c ile haberleşmeye çalışıyorum.
İlk defa i2c haberleşmesi yapacağım. Birkaç deneme yaptım ama başarısız oldum. Sizlerden bu konuda yardım istiyorum.
Ekran ile haberleşme konusunda şunu buldum:
Veri aktarımı
1. Master MRQ Düşük ayarlar
2. Slave SDA Düşük yanıtlıyor T 1dak = 100µs T 1max = 15ms
3. Master MRQ yüksek ayarlar T 2 dakika = 100US T 2max = 200u.s.
4. Slave SDA yüksek ayarlar T 3 dk = 100US T 3MAX = 200u.s.
5. Master SDA Düşük ayarlar T 4 dk = 100US T 4max = 500μs
6. Master SCL düşük ayarlar T 6min = 100US T 6max = 200u.s.
7. Master adres gönderir
8. Master MRQ Düşük ayarlar T 7 dk = 100US T 7max = 500μs
9. Master veri gönderir T 5 dakika = 1 ms T 5 maks = 10 ms
10. Master MRQ Yüksek ayarlar T 7 dk = 100US T 7max = 500μs
Mesajın formatı
Gönderilecek mesaj, ekranın bağımlı adresinden oluşur;
Sembol baytları ve veri baytları.
1. Aktarımı başlatın
2. Slave adresi
3. Sembol baytları
4. Veri baytları
5. İletimin sonu
              Sembol baytı Veri baytı Köle(slave) adresi
8 haneli TID      2            8       4Ah = 74d
10 haneli TID     3            1       04Dh = 77d
Benim ekran 8 haneli

Baytın sonundaki onay:
1. Master SCL yüksek ayarlar LSB için (En Az Önemli Bit)
2. Master SCL düşük ayarlar Veriler köle tarafından alınır
3. Master SDA yüksek ayarlar Slave SCL'yi düşük ayarlar (veri kabul edilir)
4. Master SCL yüksek ayarlar
5. Slave SDA düşük ayarlar eğer parite tuhafsa
6. Köle SCL yüksek ayarlar Master pariteyi değerlendirebilir
7. Master SCL düşük ayarlar Master onayı kabul eder
8. Slave SDA yüksek ayarlar
9. Master, MSB'yi bir sonraki bayt veya iletim sonundan gönderir
İletim sonu:
9. Master SDA Düşük ayarlar T1 = 100µs
10. Master MRQ Yüksek ayarlar T2min = 100µs T2max = 1ms
11. Master SCL yüksek ayarlar T3 = 100µs
12. Master SDA Yüksek ayarlar T4 = 100µs

Bu normalde Almanca ancak ben google translate ile türkçeye çevirdim. Anladığım kadarı ile burada iletişim için ne yapmamız gerektiği yazıyor. Bunlardan veri aktarımı bölümünde 7. ve 9. maddeleri anlamadım. Veri gönderme yapabilirim. Ancak adres gönderme nasıl oluyor?

ete

BU tercümeden bir anlam çıkarmak zor ama anladığım kadarı ile bit bazında haberleşme şeklini açıklamaya çalışmış. Buna ihtiyacın yok aslında.
I2C haberleşmede cihaz Kodu bilinmesi gerekir. Çünki aynı hatta bağlı birden fazla cihazla haberleşebilirsin. A ihazı için A kodunu B cihazı için B kodunu verirsin. Hepsi mesajı alır ve kendi kodu ile karşılaştırır ve cevap vermek gerekiyor ise o cevap verir.
Bunun dışında o cihaz içinde hangi adresteki bilgiyi alacaksın onun adresi gerekir. Geneşde eprom cinsi elemanlar içinde birden fazla adres bulunur. AMa I2C ile çalışan bir sensörde olsa olsa 3-5 adres vardır. Senin alette kaç adres var bilmiyorum ama cihaz kodu 4Ah = 74d olduğunu sanıyorum. Ancak burada da bir sorun var ne demek 4Ah = 74d 4A bir adres. Yani Hex olarak 4A veya Desimal olarak 74 cihaz adresi olsa gerek.
Yapman gereken şu;
I2CREAD DataPin,ClockPin,Control,{Address,}[Var{,Var...}]{,Label}
Control yerine $4A yazacaksın. Address yerine sıfır yaz ve ilk adresten itibaren ne geliyor almaya çalış.
Kaç byte alınacak ise o kadar değişken adı (VAR) yazman gerek. Label e gerek yok şimdilik.Örneği ben vereyim.
I2CREAD DTA,CLS,$4A,0,[AL1,AL2,AL3]
şeklinde yazarsan olacaktır.
Emin olmak adına yalnızca Al1 yaz ve ne geldiğine bak istersen. Sonra 2 li değişkenle denersin daha sonra 3 lü ve devamında birden fazla değişkenle denersin. Ya bir noktada kilitlenir çünki oradan 3 byte yollanıyor ve sen 4 byte almaya çalışırsan işlemci beklemeye geçer ve sonunda orada kalabilir.
Sonucu bildirirsin.
Ete


cemilsivas

https://wiki.carluccio.de/images/7/7a/Tid-protokoll.pdf

Ete hocam cevap için çok teşekkür ederim. Aslında bu kodu i2cwrite olarak denemiştim ama olmadı.
Hocam link olarak okuma prosedürünün orijinalini attım.
Bir de hocam adresleri tek tek denemem gerekir mi?

cemilsivas

0x94 = 10010100A (This is the I2C address of the display)
0x10 = 00010000A (Turn one light on, I did not bother to check which bit belongs to which light.)
0x01 = 00000001A (Turn the other lights off)
0x8C = 10001100A = "F"
0xA4 = 10100100A = "R"
0x8A = 10001010A = "E"
0x8A = 10001010A = "E"
0xB5 = 10110101A = "Z"
0x40 = 01000000A = " "
0x8C = 10001100A = "F"
0x9B = 10011011A = "M"
The Display has a 12 pin connector which is described as follows:

Hocam burada da böyle adresler var. Ama bu bendeki ekrandan farklı. İkisi de opel astra ekranı.

ete

Lisan Almanca hiç bilmediğim bir dil. Bir şey anlamam zor maalesef.
Her şeyden önce ne yapacağına karar vermen gerek. Bu ekrana bir bilgimi yollayacaksın yoksa oradan bir bilgimi alacaksın.
Daha fazla döküman lazım. Buradaki bilgilerle bir sonuca varmak için epeyce uğraşmak gerek.

Ete

cemilsivas

Hocam amacım bilgi göndermek. Ekran ilk açıldığında ismimi yazmak istiyorum. Yabancı sitelerde yapan birkaç kişi var. Hatta biri pic16f84a ile yapmış. Ama kodlar asm olunca pek çözemedim.

cemilsivas

Peki hocam mrq pini ile ilgili bir ayarlama yapmamız gerekiyor mu?

ete

Haberleşmede iki eleman vardır. Birisi master yani şef diyebileceğimiz ve işi yöneten eleman, diğeride Slave denilen elemandır. Bu sistemde kimin master kimin slave olduğuna karar vermek gerekiyor. Benim düşünceme göre sen (yaptığın haberleşme devresi) Master olacaksın. İşi sen yöneteceksin. Şimdi o linkte verilen pdf dosyasına bakarsan;
İŞlem sırası şöyle verilmiş;
1.   Master setzt MRQ Low , Tercümeye göre Master MRQ hattını LOW a çekiyor

2.   Slave antwortrt SDA Low T1min = 100μ s     T1max = 15ms  yani Slave buna SDA hattını LOW a çekerek cevap veriyor.  Lowda kalma süresi olsa gerek min 100us yada max. 15 ms.

3.   Master setzt MRQ High T2min = 100μ s     T2max = 200μ s , Master MRQ hattını HIGH a çekiyor ve 100-200us bekliyor.

4.   Slave setzt SDA High T3min = 100μ s     T3max = 200μ s , Slave de SDA hattını HIGH yapıyor ve oda 100-200us bekliyor.

5.   Master setzt SDA Low T4min = 100μ s     T4max = 500μ s , Master SDA hattını LOW a çekiyor, Süre 1oous - 500us.

6.   Master setzt SCL Low T6min = 100μ s     T6max = 200μ s Master SCL hattını LOW a çekiyor 100-200us

7.   Master sendet Adresse , Master adres gönderir

8.   Master setzt MRQ Low T7min = 100μ s     T7max = 500μ s , Master MRQ hattını LOW a çeker 100-500us bekler

9.   Master sendet Daten T5min = 1ms  T5max = 10ms , Master Data yı gönderir 1-10ms

10.   Master setzt MRQ High T  , Master MRQ hattını HIGH a çeker

Bu listeye bakarsan işin bir de ön protokolü var. Yalnızca bir I2C haberleşmesi değil bu iş.
Kendini master olarak gör ve listeye uygun olarak sırası ile verilen işlemleri yap.
pdf sayfasında , Datenübertragung  başlığı altında verilen resim aslında her şeyi açıklıyor.
O resimde Ma ile işaretlenen şekiller yada yerle Master tarafından Sl ile işaretlenen yerler ise Slave tarafından yapılıyor.
Sen master olarak MQR hattına bir şekil verdikten sonra Slave in ona karşılık yapması gereken şeyi beklemen ve kontrol etmen gerekiyor. BU şekilde karşılklı haberleşerek yada işaretleşerek devam edip adres ve datayı veriyorsun.


Ete

cemilsivas

Hocam yardımlarınız için çok teşekkür ederim. Sizi de yoruyorum ama kusura bakmayın. Akşam inşallah deneyeceğim. Şimdi aklımda tek soru kaldı.
"Master adres gönderir" ve  "master veri gönderir" kısmını nasıl yapacağım? i2c de hem adres hem de veri giriyoruz.

ete

Master adress gönderir kısmında A4 adresini ve peşinden ne yaptırmak istiyor isen ona ait veriyi yollaman gerekir. O displayden veri almak için komut göndermen gerekiyor.
Bak şunları sen yazdın;
0x94 = 10010100A (This is the I2C address of the display)
0x10 = 00010000A (Turn one light on, I did not bother to check which bit belongs to which light.)
0x01 = 00000001A (Turn the other lights off)
Birinicisi I2C formatındaki Code yani adrese tekabül ediyor. İkincisi işlem kodu. Veri denilen şeyde bu oluyor. Tabiiki bu değerler diğer tip display'e ait. Kendi kodlarını bulman lazım.

Ete

cemilsivas

İyi geceler Ete hocam. Bugün bu zamana kadar denemeler yaptım. Ancak başarılı olamadım. Hocam şu şekilde kod yazdım:

@ DEVICE pic16F628a
@ DEVICE pic16F628a, WDT_ON
@ DEVICE pic16F628a, PWRT_ON
@ DEVICE pic16F628a, BOD_ON
@ DEVICE pic16F628a, PROTECT_OFF
@ DEVICE pic16F628a, LVP_OFF
@ DEVICE pic16F628a, CPD_OFF
@ DEVICE pic16F628a, MCLR_OFF
@ DEVICE pic16F628a, INTRC_OSC_NOCLKOUT
TRISA=0  'A portu çıkış olarak ayarlandı.
TRISB=0  'B portu çıkış olarak ayarlandı.
PORTA=0
CMCON=7
    

DEFINE LCD_DREG PORTB 
DEFINE LCD_DBIT 4  
DEFINE LCD_EREG PORTA  
DEFINE LCD_EBIT 6  
DEFINE LCD_RSREG PORTA   
DEFINE LCD_RSBIT 7  
DEFINE LCD_BITS 4  
DEFINE LCD_LINES 2 
symbol scl=portb.3
symbol mrq=portb.2
symbol sda=portb.1
scl=0
mrq=0
sda=0
a var byte
b var byte
b=0
a=0
basla:
scl=0
mrq=0
sda=0
lcdout $fe,1,"basliyor"
pause 1000

low mrq
input sda
pause 15
if sda=1 then: b=1:goto hata
pauseus 200
high mrq
pauseus 200
if sda=0 then:b=2:goto hata
pauseus 200
output sda
low sda
pauseus 500
low scl
pauseus 200
i2cwrite sda,scl,$4A,$A,[$8A]
low mrq
pauseus 500
i2cwrite sda,scl,$4A,$A,[$A0]
pauseus 10
high mrq
lcdout $fe,1,"veri gonderim"
lcdout $fe,$c0,"bitti ",dec a
a=a+1
pause 1000

high scl
pauseus 100
low scl
pauseus 100
high sda
pauseus 100
high scl
pause 1
input sda
'if sda=1 then:b=3:goto hata  'Burası sürekli hata veriyor.
pauseus 100
input scl
if scl=0 then:b=4:goto hata
pauseus 100
output scl
low scl
pauseus 100
if sda=0 then:b=5:goto hata


output sda
low sda
pauseus 100
high mrq
pauseus 100
high scl
pauseus 100
high sda
pauseus 100
             
GOTO BASLA

hata:
lcdout $fe,1,"hata ",dec b
end

Hocam kodda belirttiğim yer dışında herhangi bir hata yok. Döngüler tamamlanıyor. Ancak veri gönderemedim. i2c ile ilgili sorun olduğunu düşünüyorum. Önerileriniz bekliyorum hocam.

ete

Hatalı olan satırda gerçekten hata var.
if sda=1 then:b=3:goto hata  satır böyle yazılmaz.
if sda=1 then b=3:goto hata  'şeklinde yada en doğrusu
if sda=1 then
   b=3:goto hata  
endif
şeklinde yazılır.
Yazdığın programın en büyük eksikliği işlemcinin hangi OSC frekansında çalıştığını belirlememişsin.
Bu durumda genelde default değerler esas alınır ama işin doğrusu ;
DEFINE OSC 4 veya hangi frekans ise buraya yazılmalı. Dahili OSC kullanıldığına göre 4Mhz olmalı ama oraya yaz lütfen.
Komutlardaki $A adres değerini anlamadım. Neden $A kullandın. Bunu kullanacak isen bir defa $0A şeklinde yazmalısın. Ama açıklamalarında 10 nolu (desimal) adres diye bir şey bahsettiğini hatırlamıyorum. Ben olsam önce sıfır nolu adreslere bakardım.

Bir diğer önemli konu da SDA ve SLC hatlarının her birinde 10K ile pullup direncinin olması zorunluluğudur. I2C haberleşme pinleri mutlaka Pullup ile çalıştırılmalıdırlar.
Bunların haricinde elimden başka bir şey gelmiyor maalesef.

Ete

cemilsivas

Hocam yardımlarınız için öncelikle çok teşekkür ederim.

Dediğiniz gibi adresi 0 olarak denedim. Ancak olmadı. Ben de bir yerde, sanırım sizin dersinizde de vardı, eeprom bellek adresinin %1010 olduğunu duymuştum. Onu da denedim. Malesef o da olmadı.

Ben de dediğinizin tam tersini yapmıştım. Yani sda dck ve mrq pinlerinin hepsini 10k ile - ye çekmiştim. Dediğinizi de deneyeceğim.

Bir de hocam araştırırken şunu buldum. Bilgi gönderdikten sonra onay prosedürü varmış. Onu da uyguladım.

Sanki hocam özelikle ekranın sda sck pinlerine cevap vermesi doğru yolda ilerlediğimi hissettirdi. Öerilerinizi uygulayıp tekrar deneme yapacağım. İnşaallah başarırım.

ete

#13
Her cihazın kendi adresi olduğunu belirtmiştim. Epromunki $A0 idi sanırım. Ama senin aletin adresi $A4 zaten .
Şöyle düşün 3 adet dolap var ve her dolapta 5 er adet raf var.
Hangi kutu olduğunu seçmek için kutu numarasını veriyorsun. Bu sende $A4, Seçilen kuut içinde hangi raff olduğunuda adres ile belirliyorsun 1. raf yada 2. ci raf gibi. Senin $A yazdığın yerde raf numarası olacak.
Kısaca Dİsplay registerlerinin adresi gerekli sana onu araştır. O displayi $A4 ile seçiyorsun ama displayin içinde hangi adrese (hangi byte da denilebilir) ulaşacaksın yada alacaksın onu bilmek gerekiyor. Rast gele olmaz. Olursada sırası ile denemen lazım.
SDA ve SCL kesin Pllup lı olması gerekir bu çok önemli yoksa haberleşemez. Çünki, o hatlar open kollektördür. Pullup yardımı ile HIGH a çekilirler. ACK denilen ve her bilgi alışverişinden sonraki el sıkışma dedilen işi Pic otomatik yapıyor zaten senin bir şey yapman gerekmiyor.

Ete

cemilsivas

S. A. hocam. Dediğiniz denemeleri akşam uyguladım. Ancak yine ekranda tepki yok. Pull-up dirençleri bağladığımda slave hiç low olmadı.
Biraz araştırma yaptım ve şu siteyi buldum.
https://www.mikrocontroller.net/topic/19516
Bu sitede slave, high için 4v low için 1 v olduğu yazıyor.

Translate'den Türkçeye çevirerek inceledim. Sadece büyük harfler olabilirmiş ve veri kısmına sadece hex kodu yazılıyormuş.

Yalnız şöyle birşey daha gördüm.
void loop () 
{ 
  MRQ_low (); 
  SDA_low (); 
  süre (get_SDA ()); // SDA düşük 
  gecikmesini (50) bekleyin ; 
  MRQ_high (); 
  süre (! get_SDA ()); // SDA yüksek 
  gecikmesini bekleyin (50); 
  SDA_low (); 
  gecikme (50); 
  SCL_low (); 
  gecikme (50); 
[b]  Wire.begin (); 
  Wire.beginTransmission (TID);[/b] 
  MRQ_low (); 
[b]  Wire.send (0x01); // 
  Wire.send (0x01) ' den sembolleri değiştirin ; // Sembolleri kapat
  Wire.send (0x01); // 
  Wire.send (0x85) sembollerini devre dışı bırak ; // B 
  Wire.send (0x8A); // E 
  Wire.send (0xA4); // R 
  Wire.send (0x8F); // G 
  Wire.send (0x83 ); // A 
  Wire.send (0x9B); // M 
  Wire.send (0x83); // A 
  Wire.send (0xA7); // S 
  Wire.send (0x86); // C 
  Wire.send (0x9E // [i][/i][/b]
  gecikme (50); 
  MRQ_high (); 
  Wire.endTransmission (); 
  SDA_high (); 
  SCL_high (); 
  MRQ_high (); 
  gecikme (1000); 
}

Bu kod ardunioda yazılmış. Benim bağlandığım gibi bağlanmaya çalışmış. Ancak master adres gönderir kısmında ekranın adres kodu gönderilmiş(Sanırım bizdeki $4A). Veri kısmında ise harflerin hex kodları gönderilmiş. Yani sizin örnekle anladığım kadarıyla hangi dolap olduğu var ama çekmece ismi verilmemiş. :-)

Biraz önce de şu asm kodlarını buldum.
   
    bcf PORTA,MRQ
 call W1ms
    bsf PORTA,MRQ
 call W1ms
 call Starti2c


 movlw H'94'
 call Sendi2c ; ("&h94")

    bcf PORTA,MRQ

 movlw H'01' ; WELCOME
 call Sendi2c 
 movlw H'01'
 call Sendi2c 
 movlw H'AE'
 call Sendi2c ;AE 8A 98 86 9E 9B 8A 40 
 movlw H'8A'
 call Sendi2c 
 movlw H'98'
 call Sendi2c 
 movlw H'86'
 call Sendi2c 
 movlw H'9E'
 call Sendi2c 
 movlw H'9B'
 call Sendi2c 
 movlw H'8A'
 call Sendi2c 
 movlw H'40'
 call Sendi2c 

 bsf PORTA,MRQ
 call Stopi2c

Yine bu kodlarda da ekranın adresi gönderilmiş, mrq pini low yapılmış ve karakterler gönderilmiş.

Bu tekniği biz nasıl uygularız hocam?
Not: Tam yazarken 628a ile yapılmış bir programa rastladım. Asm ile yazılmış.

Powered by EzPortal