Ds1302 ile Alarmlı Saat Yapımı Bölüm 3



Önceki bölümde bahsettiğim gibi bu bölümde alarm ayarlama kısmını paylaşacağım. Ayarladığımız saat ve dakika bilgisini eeprom içinde tutuyorum. Pil ile sürekli enerji olacağını düşünürsek buna gerek kalmayabilir. Eeprom için “avr/eeprom.hkütüphanesini kullanıyorum. Nongnu.org burada bir çok kütüphanenin nasıl kullanılacağı anlatılmış, bu yüzden detaya inmeyeceğim. Aşağıda “main” fonksiyonunu tekrar paylaşıyorum. Gördüğünüz gibi “alarmSaat=eeprom_read_byte((uint8_t*)0);” ve “alarmDakika=eeprom_read_byte((uint8_t*)1);” olarak iki değişkeni eepromdan okuyarak değer veriyoruz. “ayarAlarm_saat=alarmSaat;” ve “ayarAlarm_dakika=alarmDakika;” kısmıysa alarm ayarlarken kullandığım değişkenler. Bu atamayı yapmazsam alarm ayarlama ekranında saat ve dakikayı “0” olarak görürüm bu atama sayesinde önceki ayarlı değeri görerek ayarlamaya başlayabiliyorum.

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); //alarm için pin ayarlandı
        PORTB|=(1<<PORTB2);           
    while (1) {
                saat_oku();
                tarih_oku();                  
                ekran_yaz[ekran]();
                buton_kontrol();       
                alarm_kontrol();
                _delay_ms(50);
                LCD_CL;        
                _delay_ms(2);  
                 
    }
}

“while” döngüsü içinde “alarm_kontrol” fonksiyonu çağrılıyor. Saat ve dakikanın kontrolü bu fonksiyon tarafından yapılıyor. Saat - alarm saat, dakika -alarm dakikayı ve alarmın açık ya da kapalı olmasını kontrol ettiğimiz alarm değişkeni istenen şartı yerine getirdiğinde alarm çalışmaya başlıyor. Ben burada 3 döngüde bir ekran ışığını açacak şekilde ayarladım. Dilediğiniz pini “1” yaparak ses ya da ışıklı bir uyarıcı oluşturabilirsiniz.

void alarm_kontrol(){
        if ((alarm==1)&&(saat==alarmSaat)&&(dakika==alarmDakika)){
                if (ekran_say>=3){     
                        ekran_say=0;           
                        PORTB|=(1<<PORTB2);
                        }else {                       
                               PORTB&=~(1<<PORTB2);          
                        }              
                ekran_say++;
                }else{         
                PORTB|=(1<<PORTB2);           
        }      
}

Alarm durumunu bu şekilde kontrol ettik ayarlama kısmını oluşturacağınız ekranda “buton_kontrol” fonksiyonu ya da farklı bir fonksiyonla değerleri değiştirip ayarlayabilirsiniz.  Sadece son kayıt işleminde eeproma yazma işlemini yapmanız gerekir. Kodu aşağıda paylaştım.

eeprom_update_byte((uint8_t*)0,ayarAlarm_saat);
eeprom_update_byte((uint8_t*)1,ayarAlarm_dakika);
alarmSaat=ayarAlarm_saat;
alarmDakika=ayarAlarm_dakika;

Menüler arası geçiş ya da birden fazla seçenek olduğunda genellikle eşitlik söz konusu ise “switch case”  büyük-küçük ilişkisi söz konusu ise “if else” kullanmaya çalışıyorum. Bu basit saat programında her menü ayrı bir “ekran” yazan fonksiyondan oluşuyor. Bunu “switch case” ya da “if else” ile de yapabilirdim. Fakat çok karmaşık ve kontrol etmesi zor bir programla karşı karşıya kalacaktım. Facebook grubunda bir paylaşımda gördüğüm “jump table”  nedir diye araştırmaya başladım. Daha önce yüzeysel olarak geçtiğim işaretçiler (pointer) konusuna tekrar döndüm birçok kaynaktan okudum. Taha Yasin Erkan sitesinde bu konuyu anlaşılır şekilde anlatmış. Detaya inmeden olayın özü her fonksiyon ismi aynı zamanda adres tıpkı dizi isimleri gibi fonksiyonun adresini tutuyor. Fonksiyon isimlerinden işaretçi dizisi oluşturabiliyoruz. Nasıl “int *ptr; “ gibi bir işaretçi tanımlayıp adres değeri saklayabiliyorsak. “void (*foknsiyon) (void);” şeklinde fonksiyon işaretçi tanımlayabiliyoruz. Burada parantezlerin önemli olduğu yazılıydı. Bizim tanımlamamız void (*foknsiyon[]) (void)={a,b,c} şeklide olacak a,b ve c fonksiyon isimleridir. Aşağıda paylaştım dikkat ederseniz aynı dizi elemanlarında olduğu gibi fonkiyonların sırası da önemli. Main fonksiyonu paylaşımıma bakarsanız döngü içinde “ekran_yaz[ekran]();  şeklide çağrılıyor. Ekran değişkeni değeri kaç ise hemen o fonksiyona gidiliyor.

void (*ekran_yaz[10])(void)={
        ana_ekran,
        prog_gun,
        prog_ay,
        prog_yil,
        prog_saat,
        prog_dakika,
        alarm_ekran,
        prog_alarm_saat,
        prog_alarm_dakika
};



Umarım faydalı olmuştur. Burada kodun tamamını paylaşmayacağım. Bazı kısımlarını bilerek eklemiyorum. Kopyalayıp alırsanız çalışmaz bunu tekrar bir araya getirmek için emek harcamanız dolayısıyla öğrenmeniz gerekecek.

/*
 * alarm_saat.c
 *
 * Created: 26.02.2019 19:23:16
 * Author : haluk
 */


//kütüphaneler
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
//pin-port tanımları
#define DATA_PORT PORTD
#define CMD_PORT PORTB
#define DS_PORT PORTB

#define EN_ PB1
#define RS_ PB0
#define CE_ PB3
#define IO_ PB4
#define CLK_ PB5
#define DATA_7 PD7
#define DATA_6 PD6
#define DATA_5 PD5
#define DATA_4 PD4
//io tanımları
#define DATA_OUT DDRD|=(1<<DATA_7)|(1<<DATA_6)|(1<<DATA_5)|(1<<DATA_4)
#define DS_OUT DDRB|=(1<<CE_)|(1<<CLK_)
#define IO_OUT DDRB|=(1<<IO_)
#define IO_IN DDRB&=~(1<<IO_)
#define CMD_OUT DDRB|=(1<<RS_)|(1<<EN_)
//
#define EN_HIGH CMD_PORT|=(1<<EN_)
#define EN_LOW CMD_PORT&=~(1<<EN_)
#define RS_HIGH CMD_PORT|=(1<<RS_)
#define RS_LOW CMD_PORT&=~(1<<RS_)
#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_)

//lcd komutlar
//saat tanımları
#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

//buton tanımları
#define yukari 1
#define asagi 2
#define sol 3
#define sag 4
#define sec 5
#define bos 0
//değişkenler
int8_t ayarGun, ayarAy,ayarYil,ayarSaat,ayarDakika;
int8_t ayarAlarm_saat,ayarAlarm_dakika;
uint8_t saat,dakika,saniye,alarm,gun,ay, yil,alarmSaat,alarmDakika;
uint8_t ekran_say,sagSay=0,solSay=0,ekran=0;  
char csaat[3],cdakika[3],csaniye[3],cgun[3],cay[3],cyil[3],cAlarm_saat[3],cAlarm_dakika[3];

uint8_t  zil[8] =//0 adresi
{
        0x04, 0x0E,0x0E, 0x0E,0x1F,0x1F, 0x04, 0x00
};
void adcBasla(){
        ADMUX=(1<<REFS0);
        ADCSRA=(1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
}
uint16_t adcOku(uint8_t kanal){
        kanal &=0x07;
        ADMUX=(ADMUX & 0xF8) | kanal;
        ADCSRA |=(1<<ADSC);
        while(ADCSRA & (1<<ADSC));    
        return (ADC);
}
uint8_t buton_durum(){
        uint16_t butdeg= adcOku(0);
       
        if(butdeg<50){
                _delay_ms(150);
        return sag;}
        if(butdeg<150) {
                _delay_ms(150);
        return yukari;}
        if(butdeg<300){
                _delay_ms(150);
        return asagi;}
        if(butdeg<450) {
                _delay_ms(250);
        return sol;}
        if(butdeg<700) {
                _delay_ms(150);
               
        return sec;}
        return bos;
}
void buton_kontrol(){
        uint8_t buton=buton_durum();
        if (buton==yukari)
                switch (ekran){
                case 1:
                        ayarGun++;
                        if (ayarGun>=32){ayarGun=1;}
                        break;
                case 2:
                        ayarAy++;
                        if (ayarAy>=13){ayarAy=1;}
                        break;
                case 3:
                        ayarYil++;
                        if (ayarYil>=100){ayarYil=0;}
                        break;
                case 4:
                        ayarSaat++;
                        if (ayarSaat>=24){ayarSaat=0;}
                        break;
                case 5:
                        ayarDakika++;
                        if (ayarDakika>=60){ayarDakika=0;}
                        break;
                case 6:
                        break;
                case 7:
                        ayarAlarm_saat++;
                        if (ayarAlarm_saat>=24){ayarAlarm_saat=0;}
                        break;
                case 8:
                        ayarAlarm_dakika++;
                        if (ayarAlarm_dakika>=60){ayarAlarm_dakika=0;}
                        break;
                default:
                        break;
                }
       
        if(buton==asagi)
                switch (ekran){
                case 1:
                        ayarGun--;
                        if (ayarGun<1){ayarGun=31;}
                        break;
                case 2:
                        ayarAy--;
                        if (ayarAy<1){ayarAy=12;}
                        break;
                case 3:
                        ayarYil--;
                        if (ayarYil<0){ayarYil=99;}
                        break;
                case 4:
                        ayarSaat--;
                        if (ayarSaat<0){ayarSaat=23;}
                        break;
                case 5:
                        ayarDakika--;
                        if (ayarDakika<0){ayarDakika=59;}
                        break;
                case 6:
                        break;
                case 7:
                        ayarAlarm_saat--;
                        if (ayarAlarm_saat<0){ayarAlarm_saat=23;}
                        break;
                case 8:
                        ayarAlarm_dakika--;
                        if (ayarAlarm_dakika<0){ayarAlarm_dakika=59;}
                        break;
                default:
                        break;
                }      
        if(buton==sec){
                ekran++;
                if (ekran>=1){
                        ayarGun=gun;
                        ayarAy=ay;
                        ayarYil=yil;
                }
                if(ekran>=2){
                        ekran=0;
                }
        }
        if (buton==sag){
                sagSay ++;
                if (ekran==3){
                        ayarSaat=saat;
                        ayarDakika=dakika;
                }
        }
        if (buton==sol)
                solSay ++;     
}
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;
        }
}
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;
}
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);
}
void saat_ayar(uint8_t _st,uint8_t _dk,uint8_t _san){
        CE_HIGH;
        ds_data(Y_SAN);
        ds_data(bcd_yaz(_san));
        CE_LOW;
        _delay_us(2);
        CE_HIGH;
        ds_data(Y_DAK);
        ds_data(bcd_yaz(_dk));
        CE_LOW;
        _delay_us(2);
        CE_HIGH;
        ds_data(Y_SAT);
        ds_data(bcd_yaz(_st));
        CE_LOW;
}
void tarih_ayar(uint8_t _gn,uint8_t _ayy,uint8_t _yl){
       
}
void saat_oku (){
        saniye= bcd_oku(ds_oku(O_SAN));
        _delay_us(2);
        dakika= bcd_oku(ds_oku(O_DAK));
        _delay_us(2);
        saat= bcd_oku(ds_oku(O_SAT));
       
}
void tarih_oku (){
       
       
}
void alarm_kontrol(){
        if ((alarm==1)&&(saat==alarmSaat)&&(dakika==alarmDakika)){
                if (ekran_say>=3){     
                        ekran_say=0;           
                        PORTB|=(1<<PORTB2);
                        }else {                       
                               PORTB&=~(1<<PORTB2);          
                        }              
                ekran_say++;
                }else{         
                PORTB|=(1<<PORTB2);           
        }      
}
void tarih_sablon (){
        lcd_git(0,0);
        lcd_dizi("Tarih");
        lcd_git(8,0);
        lcd_yaz('.');
        lcd_git(11,0);
        lcd_yaz('.');
}
void saat_sablon (){
        
}
void alarm_sablon(){
        lcd_git(6,0);
        lcd_dizi("Alarm");
        lcd_git(8,1);
        lcd_yaz(':');
}
void gun_yaz (uint8_t _gun){
        sprintf(cgun,"%d",_gun);
        lcd_git(6,0);
        if (_gun<10){
        lcd_yaz('0');
        }
        lcd_dizi(cgun);
       
}
void ay_yaz(uint8_t _ay){
        
}
void yil_yaz(uint8_t _yil){
       
}
void saat_yaz (uint8_t _saat){
        sprintf(csaat,"%d",_saat);
        lcd_git(6,1);
        if (_saat<10)
        {
                lcd_yaz('0');
        }
        lcd_dizi(csaat);
}
void dakika_yaz (uint8_t _dakika){
       
}
void saniye_yaz (uint8_t _saniye){
       
}
void alarm_saat_yaz(uint8_t _alarmSaat){
        sprintf(cAlarm_saat,"%d",_alarmSaat);
        lcd_git(6,1);
        if (_alarmSaat<10)
        {
                lcd_yaz('0');
        }
        lcd_dizi(cAlarm_saat);
}
void alarm_dakika_yaz(uint8_t _alarmDakika){
       
}
void menu_kontrol(){          
        if (sagSay==1){
                if (ekran==0){
                        alarm++;                      
                        if (alarm>=2){
                        alarm=0;}
                        sagSay=0;
                }else if (ekran==3){
                        tarih_ayar(ayarGun,ayarAy,ayarYil);
                        ekran++;
                        sagSay=0;
                }else if (ekran==5){
                        saat_ayar(ayarSaat,ayarDakika,0);
                        ekran=0;
                        sagSay=0;
                }else if (ekran==8){
                        eeprom_update_byte((uint8_t*)0,ayarAlarm_saat);
                        eeprom_update_byte((uint8_t*)1,ayarAlarm_dakika);
                        alarmSaat=ayarAlarm_saat;
                        alarmDakika=ayarAlarm_dakika;
                        ekran=0;
                        sagSay=0;
                }else {
                        ekran++;
                        sagSay=0;
                }              
        }
        if (solSay==1){
                if (ekran==0){
                        ekran=6;
                        solSay=0;                     
                }else if (ekran==6){
                        ekran=0;
                        solSay=0;
                }else {
                        ekran--;
                        solSay=0;
                }              
        }
}
void ana_ekran(){
        tarih_sablon();
        saat_sablon();
        gun_yaz(gun);
        ay_yaz(ay);
        yil_yaz(yil);
        saat_yaz(saat);
        dakika_yaz(dakika);
        saniye_yaz(saniye);    
        if (alarm==1){
                lcd_git(15,1);
                lcd_yaz(0);
                }
        menu_kontrol();
}
void prog_gun (void){  
        tarih_sablon();
        if (ekran_say>=3){
                ekran_say=0;
                }else   {
                        gun_yaz(ayarGun);
                }      
        ay_yaz(ayarAy);
        yil_yaz(ayarYil);
        menu_kontrol();
        ekran_say++;
}
void prog_ay (void){
        
}
void prog_yil (void){
        
}
void prog_saat (void){
        saat_sablon();
        if (ekran_say>=3){
                ekran_say=0;
                }else {saat_yaz(ayarSaat);
        }
        dakika_yaz(ayarDakika);
        saniye_yaz(saniye);
        menu_kontrol();
        ekran_say++;
}
void prog_dakika (void){
       
}
void alarm_ekran(){
        alarm_sablon();
        alarm_saat_yaz(alarmSaat);
        alarm_dakika_yaz(alarmDakika);
        menu_kontrol();
}
void prog_alarm_saat (void){
        alarm_sablon();
        if (ekran_say>=3)
        {ekran_say=0;
                }else {alarm_saat_yaz(ayarAlarm_saat);
        }
        alarm_dakika_yaz(ayarAlarm_dakika);
        menu_kontrol();
        ekran_say++;
}
void prog_alarm_dakika (void){
        
}
void (*ekran_yaz[10])(void)={
        ana_ekran,
        prog_gun,
        prog_ay,
        prog_yil,
        prog_saat,
        prog_dakika,
        alarm_ekran,
        prog_alarm_saat,
        prog_alarm_dakika
};
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); //alarm için pin ayarlandı
        PORTB|=(1<<PORTB2);           
    while (1) {
                saat_oku();
                tarih_oku();                  
                ekran_yaz[ekran]();
                buton_kontrol();       
                alarm_kontrol();
                _delay_ms(50);
                LCD_CL;        
                _delay_ms(2);  
                 
    }
}



Hiç yorum yok:

Yorum Gönder