Bir önceki bölümde
Ds1302 data gönderme fonksiyonunu paylaştım. Veri okurken ya da yazarken adres
komutu göndermemiz gerektiğini belirtmiş ve tablo paylaşmıştım.
Bu tabloda sol tarafta
okuma ve yazma adresleri bulunmakta. Tablo rehberliğinde saniye bilgisini
göndereceğim sonrasında okuma yapacağım. Diğer ayar ve okumalarda aynı şekilde
yapılmaktadır. Okuma ya da yazma için ilk şart CE “1” yapmaktı. Bunun ve diğer
işlemler için makrolar tanımladım. Aşağıda paylaştığım bu tanımları sizde
istediğiniz şekilde yapabilirsiniz.
#define CE_HIGH DS_PORT|=(1<<CE_)
#define CE_LOW DS_PORT&=~(1<<CE_)
#define IO_HIGH DS_PORT|=(1<<IO_)
#define IO_LOW DS_PORT&=~(1<<IO_)
#define CLK_HIGH DS_PORT|=(1<<CLK_)
#define CLK_LOW DS_PORT&=~(1<<CLK_)
|
Yine kolaylık
olması için adres verilerini de benzer tanımlamalar ile yaptım. Bu sayede “0x80” gibi adreslere sürekli bakmak zorunda kalmadım. Saniye yazmak için “Y_SAN” okumak
için “O_SAN” gibi tanımları aşağıda paylaşıyorum.
#define Y_SAN 0x80
#define O_SAN 0x81
#define Y_DAK 0x82
#define O_DAK 0x83
#define Y_SAT 0x84
#define O_SAT 0x85
#define Y_GUN 0x86
#define O_GUN 0x87
#define Y_AY 0x88
#define O_AY 0x89
#define Y_YIL 0x8C
#define O_YIL 0x8D
|
Gelelim saniye
ayarlayan fonksiyonumuza. Saat ya da dakika da aynı şekilde ayarlanır hatta
bunlar tek bir fonksiyon içinde yapılması doğru olanı, karışıklık olmaması için
ayrı olarak tanımlıyorum.
void saniye_ayar(uint8_t sn){
CE_HIGH;
ds_data(Y_SAN);
ds_data(bcd_yaz(sn));
CE_LOW;
}
|
Fonksiyon ilk önce CE pinini “1”
yapıyor, ds_data fonksiyonu çağrılıyor ve saniye ayarı için Y_SAN=“0x80”
sayısını parametre olarak veriyor. Ardından yine ds_data çağrılıyor ve
saniye_ayar fonksiyonunun parametresi olan “sn” değeri neyse onu parametre
olarak alıp gönderiyor.
void saniye_oku (){
saniye= bcd_oku(ds_oku(O_SAN));
}
|
Ayarladığımız değeri sürekli
olarak okuyup ekrana yazmamız gerekiyor. Bunun için saniye okuma fonksiyonu
tanımlıyoruz. Bu fonksiyonda okunan değer tanımladığımız bir değişkene eşitlemeliyiz.
Bunu direkt değer eşitlemek şeklinde yapıyorum. Saniye bilgisinin bulunduğu “0x81”=
O_SAN adresini parametre olarak ds_oku fonksiyonuna gönderiyoruz. Saniye
ayarlayan ve okuyan iki fonksiyonda adres bilgisi dışında BCD dönüşümü
yapıyoruz. Saniye de olduğu gibi tarih ve saat bilgilerini ayarladık ve döngü
içinde sürekli olarak okuyarak değişkenlere atadık. Bu değerleri çıktı birimi
olarak ne kullanıyorsak oraya yazdırabiliriz. Ds1302 ile ilgili kısımları
halletmiş olduk artık menü düzeni hakkında yaptıklarımı paylaşabilirim.
Kullandığım Lcd keypad yön
butonlarına sahip. Bu butonlar olmasa da kendimiz benzer yapıyı
oluşturabiliriz. Lcd keypad butonlara bastığımda farklı analog değerleri bağlı
olan A0 pini olarak bildiğimiz PORTC0 pinine gönderiyor. Yapılan okumada
değerlere göre hangi buton olduğunun tespiti yapılıyor. PORTCO pinini ADC
okuması yaparak butonların gönderdiği değerleri görebilirsiniz. Aşağıdaki fonksiyon
bu değerlere göre değer döndüren bir fonksiyon. Pindeki değer “50” den küçükse “sağ”
değerini döndürüyor. Sağ değeri programın başında “#define sag 4”
olarak tanımlı. Yani derleyici sag gördüğü her
yere “4” yazıyor hafızaya bu şekilde atılıyor. _delay komutunu butona
basıldığında birden fazla kez dönüş yapmaması için kullandım. Butonların “1” ya
da “0” olma durumu kontrol edilemediği için buna mecburum. Diğer türlü pin
durumu kontrol ettiğimde zaten buna gerek kalmayacaktır.
uint8_t buton_durum(){
uint16_t butdeg= adcOku(0);
if(butdeg<50){
_delay_ms(100);
return sag;}
if(butdeg<150) {
_delay_ms(100);
return yukari;}
if(butdeg<300){
_delay_ms(100);
return asagi;}
if(butdeg<450) {
_delay_ms(100);
return sol;}
if(butdeg<700) {
_delay_ms(100);
return sec;}
return bos;
}
|
Buton durumunu kontrol ettik hangi
butona basıldığını öğrenebiliyoruz. Bu bilgiyi kullanarak örneğin yukarıya
basıldığında değişkenlerin değerinin artmasını sağlayacak başka bir fonksiyon
tanımlamamız gerekiyor. Bunu buton durumu içinde de yapabilirdik. Ama her
fonksiyon bir iş yapmalı birden fazla iş yapan fonksiyonların ayrılması
gerektiği okuduğum birçok kaynakta yazılıydı.
void buton_kontrol(){
uint8_t buton=buton_durum();
if (buton==yukari)
ayar++;
if
(buton==asagi)
ayar--;
if(buton==sec){
ekran++;
if(ekran>=2)
ekran=0;
}
if (buton==sag)
sagSay ++;
if (buton==sol)
solSay ++;
}
|
Buton kontrol fonksiyonu
butonların durumunu kontrol eden buton_durum fonksiyonu ile aldığımız değeri buton
adında lokal bir değişkene atıyor. Değişkenin değerine göre “if” kontrolcüsüyle
genel değişkenlerin değerlerini azaltıyor ya da artırıyoruz. Bu değişkenler
ekranlar arası gezinmemizi, ekranda gördüğümüz değerlerin artması ya da
azalması işlemlerini yapmamıza olanak veriyor. Örnek olarak ana ekranda
(ekran=0 iken) zamanı ve tarihi yazdırıyorsak, “sec” tuşuna basıldığında (ekran=1
olduğunda) tarih ayarı yapılan ekrana geçiş yapıyoruz. İlk bölümde yer alan
videoda 9 farklı ekran bulunmaktadır. Fonksiyonda ekran “0” ve “1” olabilir. Bunun
nedeni ayarlar arası gezinirken bu ekran değerinin artmasına izin verirsem “sec”
butonu basıldığında örneğin “yıl” ayarının yapıldığı ekrana gidilmesine neden olacaktır.
void ana_ekran(){
saat_yaz();
tarih_yaz();
if (buton_durum()==sag)
{ alarm++;
}
if (alarm>=2)
{alarm=0;}
if (alarm==1)
{lcd_git(15,1);
lcd_yaz(0);}
if (solSay==1)
{ekran=6;}
sagSay=0;
solSay=0;
}
|
Ana ekranda yapılan işlemler
yukarıdaki gibidir. Sol tuşa basıldığında “solSay=1”
olduğundan “ekran=6;” yapılıyor. Ekran 6 ise alarm
bilgisini yazıldığı ekrandır. Bu ekrana geçildiğinde aşağıda görüldüğü gibi
ekrana farklı bilgiler yazılmaktadır. Yine bu ekranda da buton durumuna göre
ana ekrana dönülebilmekte ya da alarm ayarlarının yapıldığı “ekran 7” ye
geçilmekte.
void alarm_yaz(){
sprintf(cAlarm_saat,"%d",alarmSaat);
sprintf(cAlarm_dakika,"%d",alarmDakika);
lcd_git(6,0);
lcd_dizi("Alarm");
lcd_git(6,1);
if (alarmSaat<10)
{
lcd_yaz('0');
}
lcd_dizi(cAlarm_saat);
lcd_yaz(':');
if (alarmDakika<10)
{
lcd_yaz('0');
}
lcd_dizi(cAlarm_dakika);
if (solSay==1)
{ekran=0;
solSay=0;}
if (sagSay==1)
{ekran=7;
sagSay=0;}
}
|
Buraya kadar olan kısım menü
düzeni hakkında yeterli bilgi vermiştir. Bu ekranlar arası geçişte buton durumunun
kontrolü saat ve tarih bilgisinin okunması ana döngü içinde sürekli yapılmakta.
Biz ana ekranı görürken tekrar ve tekrar fonksiyonlar arası gezilmektedir. Bunu
anlamak için main fonksiyonu ve while döngüsüne değinmek gerekiyor. Aşağıda paylaştığım
main fonksiyonu lcd ve ds1302 için gerekli ayarlamaları içeriyor. Ayrıca sonraki
bölüme kalan alarm ayarlanması kısmının önemli bir noktası olan eepromdan okuma
komutları bulunmakta. While sonsuz döngüsünü incelerseniz demek istediğimi
anlarsınız. Gördüğünüz gibi saat-tarih okunuyor. Bu bilgiler ile ekran yazılıyor,
buton ve alarm durumları kontrol ediliyor. Ekranın çok hızlı hareket etmemesi
için mecburi bir bekleme sonrası ekran siliniyor. Tüm bunlar tekrar baştan
başlıyor böylece ekranlar arası geçiş yapabiliyor ve değerleri değiştirebiliyoruz.
int main(void){
lcd_basla();
_delay_ms(2000);
lcd_krk(0,zil);
alarmSaat=eeprom_read_byte((uint8_t*)0);
alarmDakika=eeprom_read_byte((uint8_t*)1);
ayarAlarm_saat=alarmSaat;
ayarAlarm_dakika=alarmDakika;
adcBasla();
DS_OUT;
DDRB|=(1<<PORTB2);
PORTB|=(1<<PORTB2);
while (1) {
saat_oku();
tarih_oku();
fyaz[ekran]();
buton_kontrol();
alarm_kontrol();
_delay_ms(150);
LCD_CL;
_delay_ms(2);
}
}
|
Sonraki bölümde alarm ayarlama ve
kontrolünü anlatacağım. Ekranlar arası geçişi “if” ya da “switch” ile yapmaktan
kurtaran yeni öğrendiğim işaretçiler ile fonksiyon çağırma yöntemini
paylaşacağım.
Hiç yorum yok:
Yorum Gönder