Saat yapımında kullandığım RTC (gerçek zamanlı saat) entegresi olan Ds1302’yi kısaca anlatarak başlayalım. Her zaman olduğu gibi Datasheet en önemli yardımcımız, internette oldukça fazla kaynak ve anlatımda bulunmakta. 2100 yılına kadar kayıtlı bir takvimi var 28-29 Şubat için çalışma yapmamıza gerek yok. Aşağıda pin ve bağlantı şeması bulunmakta.
X1-X2 pinlerine 32768
kHz kristal osilatör bağlantısı önemli entegreye oldukça yakın olmalı ve
gürültüden korumak için GND ile bacaklar sarılmalı kristal yine GND üstüne
yatırılmalı. Isı etkisi saatin şaşmasına neden olabilir. Kristal
bağlantı notlarını inceleyebilirsiniz.
Vcc2 ana besleme pini 5v-2v
çalışabiliyor. Eğer Vcc2, Vcc1 den 0,2 volt ve üstünde ise bu pinden beslenir. Bu
fark düştüğünde Vcc1 pininden güç alır. Vcc1 pil bağlantısı yapılan pindir
CR2032 pili takılabilir. Pil olmazsa enerjisi kesildiğinde tarih ve saat bilgisi
silinir.
Ds1302 3 kablo ile eşzamanlı iletişim kurulan bir entegre bu iletişimi CE (kontrol), I/O (data) ve SCLK
(senkron için saat darbesi) pinleriyle yapmakta. Aşağıda veri alış verişinin
zamana göre gösterimi mevcut.
CE pini veri alış
verişi yokken “0” durumda ancak “1” olduğunda okuma yazma yapılabilmektedir. Yine
önemli bir konu okuma için önce adres yazmak sonra veri okumak gerekir. Burada
saat darbe sinyallerine bakacak olursak yazarken yükselen kenar, okurken düşen
kenar sayılarak işlem yapılır. Saat darbesi gönderildikçe I/O pini üstünde “1”
ya da “0” olma durumuna göre veri okuma/yazma yapılır.
Veri okuma yazma
işlemlerinde düşük bitle başlanır. Adres komutu ya da tarih saat bilgisi daima
bu şekildedir. Aşağıda adres/komut byte yapısı ve adres bilgileri, verinin
nasıl kaydedilip okunacağını gösteren tablo bulunmaktadır.
Ds1302 incelemesi
yazmak gibi bir amacım yok bu yüzden detaya inmeyeceğim. Adres/komut byte ilk
biti “0” ise yazma “1” ise okuma yapılır. Örnek olarak tabloda ilk satırda 0x81
ve 0x80 okuma-yazma olarak görünmekte. Ds1302 ye 0x81 verisini yollarsak o bize
saniye verisini yollar ya da 0x80 yollarsak bizden saniye verisini almak için
bekler. Bu tabloda yer alan aralıksız okuma koruma modları 12/24 saat seçimine
değinmeden geçiyorum. Tabloda dikkat edilmesi gereken saniye, saat ve tarih
bilgilerinin 10 saniye-saniye ya da 10 dakika-dakika şeklinde ayrı yazılıyor ya
da okunuyor olması. İkilik sistem de onluk sistem gibi rakamların tutulması BCD
olarak adlandırılıyor.
BCD örnekle
anlatılması gereken bir sistem. 18 sayısını ele alalım bunu onluk sistemde 1 ve
8 olarak basamaklarına ayırabiliriz. 18 sayısı ikilik sistemde “0001 0010”
olarak yazılır. BCD olaraksa “1” ve “8” sayıları ayrılarak yüksek dört bite “1”
düşük dört bite “8” yazılarak gösterilir. BCD olarak 18 sayısı “0001 1000”
yazılır. Bu sayı onluk sistemde “18” değil “24”dür. BCD gösterim onaltılık “HEX”
tabanda onluk yazılan sayıya eşittir. 0x18=BCD”0001 1000”
Bu dönüşümü yapmak
kolay bunun için formüller var. Sayıyı tabanlarına ayırmak ve tekrar
birleştirmek gerekir. Onluk tabanda bir sayıyı “10” bölmek ya da çarpmak bir
basamak kaydırdığı gibi ikilik tabanda “2” yani “0b0000 0010”, onaltılık
tabanda “16” ya da “0x10”(onluk tabanda 16) bölmek ya da çarpmak bir basamak
artırır-azaltır. BCD çevrimi sayıyı hangi tabanda işlemek istediğinize bağlı
olarak formül değişebilir. DEC-BCD için sayıyı basamaklarına ayıralım. “1” ve “8”
sayılarının karşılıkları BIN “0b0001” ve “0b1000” HEX olarak “0x01” ve “0x08”
dir. İlk basamak yüksek dört bite yazıldığında “0b0001 1000” ya da “0x18”
halini alır. Bunu formül olarak yazarsak “DecBcd ilk basamak=(18/10) ve DecBcd ikinci
basamak=(18%10) olur. (% mod alma işlemidir bölme işlemi yapıp kalanı yazar)
İlk basamak yüksek dört bite yazmak için ya (<<4) 4 bit sola kaydıracağız
ya da “16”(0x10) ile çarpacağız. Son olarak formül DecBcd= (18/10*16)+(18%10)
olacaktır. Benim tercihim DecBcd=((18/10)<<4)+(18%10)=0b00011000=0x18 şeklindedir.
(onluk tabanda 24)
BCD-DEC için yapılan işlemi
tersine çevireceğiz. Yüksek dört bit bizim onlar basamağımız düşük dört bit ise
birler basamağımızdaki sayıyı verir. 0x18=0b0001 1000
sayısının yüksek dört bitini almak için düşük dört biti atmalıyız. Yukarıda bahsettiğim
gibi sayıyı (0x18/16) bölersek ya da (>>4) 4 bit sağa kaydırırsak aynı
işlemi yapmış oluruz. Sonuçta 0x01=0b0001=”1” sayısını buluruz. Birler basamağı
için yüksek bitleri atmamız gerekir bunun için (0x18%16) ya da (0b0001
1000&0b0000 1111) işlemleri yapılabilir. Sonuç olarak 0x08=0b1000=”8” sayını
buluruz. 18=(1*10)+(8) olduğuna göre son olarak formül BcdDec=((0x18/16)*10)+(0x18%16)
olacaktır. Bu dönüşüm için benim tercihim BcdDec=(0x18>>4)+(0x18&0xF0).
Bu şekilde daha anlaşılır olduğunu düşünüyorum. Kodu inceleyen biri ne yapılmak
istendiğini anlayabilir, diğer türlü bilgisi olmayan biri için 16 ya bölünmesi
anlamsız gelebilir. Ds1302 BCD biçimini kullandığı için uzun sürse de anlatmayı
gerekli görüyorum. Veri alış verişinde bu değişimi
yapmak için bu iki fonksiyonu kullanmak gerekir.
uint8_t bcd_yaz(uint8_t bcdyaz){
return (((bcdyaz/10)<<4)+(bcdyaz%10));
}
uint8_t bcd_oku(uint8_t bcdoku){
return ((bcdoku>>4)*10)+(bcdoku&0x0F);
|
Bu uzun anlatım
sonrası verinin nasıl gönderildiğine kısaca değineceğim. Bunun için yukarıda
belirttiğim gibi CE pini “1” olmalı sonrasında düşük bit önce olarak okuma ya
da yazma komutu gönderilmeli bu gönderimi yapmak için I/O pinine bağlı pin
çıkış olarak verinin durumuna göre “1” ya da “0” olacak sonrasında saat
darbesiyle Ds1302 registerine veriyi aktaracaktır. Aşağıda ds_data fonksiyonu
bir byte veri gönderme işini yapmaktadır. Parametre olarak aldığı veriyi çıkış
yapılan data pinini düşük bitten başlayarak “1”ya da“0” yaparak aktarır. Sonrasında
saat darbesi gönderilir. “for “ döngüsüyle bu işlem 8 bit gönderilene kadar
tekrar edilir. Her bit sonrası “1” bit sağa kaydırma yapılır. CE pinini yazma
işlemi için ayrı bir fonksiyonda “1” yaptığımdan burada bir değişim yok.
void ds_data (uint8_t dsdata){
IO_OUT;
for (uint8_t i=0;i<=7;i++)
{
if (dsdata&0x01)
{
IO_HIGH;
}else{
IO_LOW;
}
dsdata>>=1;
CLK_HIGH;
_delay_us(10);
CLK_LOW;
}
}
|
Okuma işlemi için
gerekli fonksiyonu tanıtınca ilk bölümü tamamlamış olacağım. CE pini “1”
yapılarak işlem başlıyor, okumadan önce hangi adresten okuma yapılacağını
bildirmemiz gerekli bu yüzden fonksiyona parametre olarak adres verisini
giriyoruz. ds_data fonksiyonu ile adresi yazıyoruz. I/O pinine bağlı data pinin
giriş yaparak data pinini kontrol ediyoruz. Pin “1” ise değişkenin yüksek
bitine “1” yazıyoruz saat darbesiyle başa dönüp değişkendeki veriyi 1 bit sağa
kaydırıyoruz. İlk okunan bit düşük bit olduğundan döngü bitimi ilk okunan veri
düşük bite kaydırılmış olur.
uint8_t ds_oku (uint8_t dsadr){
CE_HIGH;
ds_data(dsadr);
IO_IN;
uint8_t dsoku=0x00;
for (uint8_t i=0;i<=7;i++) {
dsoku>>=1;
if (PINB&(1<<IO_))
{
dsoku|=0x80;
}
CLK_HIGH;
_delay_us(10);
CLK_LOW;
}
IO_OUT;
CE_LOW;
return dsoku;
}
|
İkinci bölümde saat, tarih ayarı, okunması ve menü yapısı hakkında bilgi vereceğim.
Hiç yorum yok:
Yorum Gönder