U

DS1307 kullanımı..

Başlatan umitco, 30 Eylül 2011, 01:52:33

ete

#15
DS1307 de registerlerin okunma sırası önemlidir. Çünki aletin hafızasında o sıra ile yer alırlar.
Dolayısıyla arada olan bir registeri kullanmasanızda ondan sonrakini kullanıyorsanız kullanmadığınızıda okumak zorundasınız. Ama en sondaki istenirse okunur istenirse okunmaz.

Gelelim sorunlara; Programında hatalar var. Hatalardan birisi ,
SN=((SN>>4) & $35)*10+(SN & 35)   komutunda  başta hem $35 kullanmışsın diğerlerinde direk 35 kullanılmış. Bu 35 de nerden çıktı anlamadım. Bnece 35 rakamıda pek doğru değil. Sebebini anlamak için register haritasına bakmak lazım.
SN registerine yerleşim şekli şöyle;
Bit7=CH yani Clock Halt biti. Bu bit 1 ise saat durur. İlk çalışmada , saat ayar edilmemiş ise bu bit 1 olarak okunur. Dolayısıyla hem saat ayarlanmalı hemde bu bit sıfırlanmalıdır.
Sonraki 3 adet bit (%0xxx0000) ise saniye değerinin onlar hanesini göstermektedir.
Sonraki 4 bit ise saniye değerinin birler hanesini göstermektedir.
Bu durumda SN değerini normal desimal değere çevirmek için sırası ile;
- onlar hanesi bitleri alınıp sağa 4 bit kaydırılmalı ve bu sayı 10 ile çarpılmalıdır. Şimdi gelelim senin 35 rakamının yanlışlığına;
  Onlar hanesini yerinden almak için Temp=SN & %01110000 işlemine tabi tutmak gerekir. Burada "1" ile gösterilen bitleri çekip alacağız. Peki nedir %01110000 sayısının değeri  112 dir. Hex olarak ise 70 değerini alır. Sen burada $35 kullanmışsın ama sanırım desimal 35 olacak idi bu ki bu sayı yanlış.
Temp=SN & $70  işlemi bize Onlar hanesini aldırdı ancak bunu tam olarak okuyabilmek için 4 bit sağa kaydırmak gerekecek.
Temp=Temp>>4   şeklinde yapıyoruz. Birde bunu 10 ile çarparsak istediğimizi elde etmiş oluruz.  Temp=Temp*10
Geriye saniye değerinin birler basamağını alıp bu sayıya eklemek kalıyor. Onuda SN=temp+(SN & %00001111) şeklinde yaparız. Şimdi bir örnek hesap yapalım. Sn değeri 56 olsun Bu 56 değeri register okunduğunda aşağıdaki şekilde okunacaktır;
SN=%01010110   ,
Temp=SN & $70=%01010000  ==> Temp=Temp>>4 =%00000101  ==> temp=temp*10=50 ve SN=50+6=56 olarak çevrilmiş olacaktır.
Bu işi tek satırda yaptıracak komut,  SN=((SN & $70)>>4)*10+SN & $0F şeklinde olamsına rağmen hatalı sonu. veriyor. Onun yerine; TEMP=((SN & $70)>>4)*10: SN=TEMP+(SN&15) demek daha doğru oluyor.

Aynı hesabı DAK için yapalım. DAK registeri yerleşim şekli,
Bit.7= 0 (daima) , Sonraki 3 bit onlar hanesi değeri, ve sonraki 4 bit ise birler hanesi değeridir.
O halde DAK çevrimi,  TEMP=((DAK & $70)>>4)*10:DAK=Temp+(DAK&15)

Aynı hesabı Saat registeri için yapalım; Register yerleşim şekli,
Bit7=0, Bit6=12/24 saat ayrımı (1 olursa 12 saat, 0 olursa 24 saat).  Bit5=24 saat modda 10lar biti 12 saat modda AM/PM biti, Bit4=10 lar biti. diğer dor bit ise birler basamağı değeridir. Saatimiz 24 saat mod ile çalışıyor kabul edelim.
Bu durumda Bit7 ve Bit6, 0 olacaktır. Geriye 2 bitlik bir değeri okumak kalıyor. O halde,
Temp=((SAAT&%00110000)>>4)*10: SAAT=TEMP+(SAAT&15)

Sıradaki register haftanın günü registeridir. Yalnızca ilk 3 bit okunarak 1-7 arasındaki değer bulunur.
Sonraki register Ayın Günü registeri dir. Yerleşim şekli, %00xx0000 şeklinde xx bitleri onlar basamağı, sonriki 4 bit ise birler basamağıdır. Bu durumda ; Temp=((AYGUN & %00110000)>>4)*10: AYGUN=TEMP+(AYGUN&15)

Sıradaki register AY registeridir. Yerleşim şekli %000x0000 x biti onalr basamağı ve kalan 4 bit ise birler basamağını vermektedir. Böylece çevrim, Temp=(AY & %00010000)>>4)*10 : AY=Temp+(AY&15)

Sıradaki register Yıl registeri olup soldaki 4 bit onlar basamağı ve sağdaki 4 bit ise birler basamağına aittir.
Temp=((YIL& %11110000)>>4)*10: YIL=Temp+(YIL&15) şeklinde çevrilir. Böylece bütün çevrimler yapılmış olur.
Bu registerlerin bir ayar sonrası tekrar yerlerine kendi formatlarına çevrilerek yazılması gerektiğini unutma. Bu durumda ters çevirme işlemi yapılarak sayı regsiter formatına çevrilmelidir.

Ete

Edit: Tek satırlık komutların neden yanlış hesap yaptığını anladım. Şu şekilde yazılırsa sonuç doğru olmaktadır.
SN=((SN & $70)>>4)*10+SN & $0F  yerine   SN=((SN & $70)>>4)*10+(SN & $0F)  şeklinde yazılmalıdır.
Sondaki ifade parentez içinde olmaz ise sonuç yanlış çıkmaktadır. Diğerleride tek satırda yazılabilir.


Mucit23

Anladım hocam. Gerekli düzenlemeleri yaptım. Şimdi düzgün bir şekilde çalışıyor. Hocam yazma programında sorun yok galiba Değilmi?
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

Yazma programı derken registerlerin ayar için yerlerine geri yazılmasını kast ediyorsan yukarıdaki işlemin teris yapılması lazım.
Bu seferde elinde SN rakamı var. 35 olsun.
Bunu 3 rakamını %0011  alırız. 5 rakamınıda %0101 şeklinde alırız. SOnra bunları %00110101 şeklinde birleştirmek gerekecek.
İşte şöyle;
SECOND =(SN DIG 1)<<4+SN DIG 0
MINUTE=(DAK DIG 1)<<4+DAK DIG 0
HOUR=(SAAT DIG 1)<<4+SAAT DIG 0       
diğerlerinide buna benzer şekilde yapabilirsin.

Ete

Mucit23

Tamam hocam. İlginiz için teşekkür ederim.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

Mucit23

#19
Merhaba

Ds1307 den saat bilgisini alıyorum. SQW bacağındanda saati kalibre edebilmek için direk osc frekansını alayım dedim ama olmadı. Pinden sürekli Lojik 1 Alıyorum.

SQW bacağı galiba open collektör olarak çalışıyor. Datasheet te pull-up yapın demişler. Bende SQW Bacağını 4.7K ile pull-up yaptım. Ardından SQW ile GND arasına Led bağladım.

Şimdi DS1307 çalışmaya başladığında yani ben saati okurken LED sürekli yanıyor. SQW bacağında herhangi bir sinyal göremiyorum.

Normalde 0 ve 1. bitler frekans seçim bitleri. 32768Hz için ikisinde 1 yapmışım. 4. Bit SQW enable biti. Bu bitide 1 yaptım.

Sonuç olarak 7. Registere Hem 0x13 Yazıp denedim Hemde 0x93 Yazıp denedim sonuç alamadım. 1 Hz için 0x10 yazıyorum oda yok. Sürekli lojik 1...

İlgili bölümü ayarlamak için Kullandığım kodlar.

   I2C_Start(); 
   I2C_Addr(0xD0);      // WR to RTC
   I2C_Write(0x07);     // Control Register
   I2C_Write(0x13);     // Enable squarewave output pin
   I2C_Stop();
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

Yaptığın iş teorik olarak doğru. Çalışması gerekir idi. Başka bir sorunun var demekki.
OUT biti, frekans çıkışını kullanmadığın zaman frekans çıkış bacağının beklemesi gereken konumu belirliyor.
Frekans çıkış bacağı (SQW/OUT) LOW da  beklesin diyorsan SQWE=0 ve OUT=0 yapman yeterli oluyor.
Frekans çıkış bacağı (SQW/OUT) hıgh da  beklesin diyorsan SQWE=0 ve OUT=1 yapman gerekiyor.

Bana kalırsa led ile deneme yaparken çıkışı 1 hz olarak ayarla. zira 32768 Hz lik bir sinyalde led sürekli yanıyor gözükebilir.
Diğer taraftan bu çıkışın led sürecek kadar bir akım sağlayabileceğini hiç sanmıyorum. Bir yerlerde okudum hatırlıyorum. Çıkış yalnızca sinyal olarak değerlendirilmeli diyor idi. Bu nedenle bağladığın led çıkışı muhtemelen bozmuştur. Bir başkasını çıkışı transistörle sürerek denemelisin.

Ete

Mucit23

Dediğiniz gibi olabilir. Başka bir ds1307 ile deneyeyim. Yine bacağı pull-up yapıp osiloskop ile bakayım. Sonuç alınması gerekir.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

karacan451

I2CWrite PORTA.1,PORTA.0,$D0,$07,[%00010000]

Yukarıdaki kodu aynen yazdım SOUT (ds1307) pini çalıştı.

$D0 nedir onu anlamadım onun yerine $A0  yazdım çalışmıyor onu açıklar mısınız?

ete

I2C haberleşme sisteminde hatta bağlanan her bir I2C cihazın bir cihaz numarası vardır. Aynı hatta birden fazla ve farklı cihazlar bağlanabileceği için istediğin cihaza ancak cihaz numarası ile ulaşabiliyorsun. $D0 da DS1307 nin cihaz numarasıdır. $A0 genelde epromların cihaz numarası olarak bilinir.

Ete

Powered by EzPortal