RTC alarm interrupt

Bowman

Üye
Katılım
7 Ekim 2022
Mesajlar
98
Merhabalar. Elimde NXP'nin PCF85063A RTC entegresi bulunuyor. Zamanı set edip saniye saniye zamanı okuyabiliyorum onda sorun yok. Fakat alarm için interrupt alamıyorum malesef. set_alarm() diye bir fonksiyonum var. Saniye,dakika,saat,gün,haftanın günü şeklinde parametreleri veriyorum. Keil'de watch ekranında set ettiğim değerleri görebiliyorum.

rtc_int.png



C:
void PCF85063A::set_alarm(uint8_t alarm_hour, uint8_t alarm_minute, uint8_t alarm_second, uint8_t alarm_day, uint8_t alarm_weekday)
{
        //uint8_t setAlarm[5];
    
        if (alarm_second <99)                                                            // second     
        {                       
            alarm_second = constrain(alarm_second, 0, 59);
            alarm_second = decToBcd(alarm_second);
            alarm_second &= ~RTC_ALARM;
    }
        else
        {
            alarm_second     = 0x0;
            alarm_second |= RTC_ALARM;
    }

        if (alarm_minute <99)                                                            // minute
        {                                       
            alarm_minute = constrain(alarm_minute, 0, 59);
            alarm_minute = decToBcd(alarm_minute);
            alarm_minute &= ~RTC_ALARM;
    }
        else
        {
            alarm_minute     = 0x0;
            alarm_minute |= RTC_ALARM;
    }

    if (alarm_hour <99)
        {                                        // hour
            alarm_hour = constrain(alarm_hour, 0, 23);
            alarm_hour = decToBcd(alarm_hour);
            alarm_hour &= ~RTC_ALARM;
    }
        else
        {
            alarm_hour = 0x0;
            alarm_hour |= RTC_ALARM;
    }

    if (alarm_day <99)
        {                                        // day
            alarm_day = constrain(alarm_day, 1, 31);
            alarm_day = decToBcd(alarm_day);
            alarm_day &= ~RTC_ALARM;
    }
        else
        {
            alarm_day = 0x0;
            alarm_day |= RTC_ALARM;
    }

    if (alarm_weekday <99)
        {                                    // weekday
            alarm_weekday = constrain(alarm_weekday, 0, 6);
            alarm_weekday = decToBcd(alarm_weekday);
            alarm_weekday &= ~RTC_ALARM;
    }
        else
        {
            alarm_weekday = 0x0;
            alarm_weekday |= RTC_ALARM;
    }
        
        enable_alarm();
        
        setAlarm[0] = alarm_second;
        setAlarm[1] = alarm_minute;
        setAlarm[2] = alarm_hour;
        setAlarm[3] = alarm_day;
        setAlarm[4] = alarm_weekday;

        
        I2C_WriteMultiBytesOneReg(I2C0,I2CADDR,RTC_SECOND_ALARM,setAlarm,5);
}

void PCF85063A::read_alarm()
{
    //uint8_t readAlarm[5];
    
    I2C_ReadMultiBytesOneReg(I2C0,I2CADDR,RTC_SECOND_ALARM,readAlarm,5);
    
    readAlarm[0] = alarm_second;
    readAlarm[1] = alarm_minute;
    readAlarm[2] = alarm_hour;
    readAlarm[3] = alarm_day;
    readAlarm[4] = alarm_weekday;
    
    if(RTC_ALARM & alarm_second)                                                    // check is AEN = 1 (second alarm disabled)
    {
        alarm_second = 99;                                                                    // using 99 as code for no alarm
    }
    else
    {                                                                                                            // else if AEN = 0 (second alarm enabled)
        alarm_second = bcdToDec(alarm_second & ~RTC_ALARM);    // remove AEN flag and convert to dec number
    }

    if(RTC_ALARM & alarm_minute)               
    {
        alarm_minute = 99;                       
    }
    else
    {                                   
        alarm_minute = bcdToDec(alarm_minute & ~RTC_ALARM);   
    }

    
    if(RTC_ALARM &  alarm_hour)               
    {
        alarm_hour = 99;                       
    }
    else
    {                                   
        alarm_hour = bcdToDec(alarm_hour);   
    }

        
    if(RTC_ALARM & alarm_day)               
    {
        alarm_day = 99;                       
    }
    else
    {                                   
        alarm_day = bcdToDec(alarm_day);   
    }
    
    if(RTC_ALARM & alarm_weekday)               
    {
        alarm_weekday = 99;                       
    }
    else
    {                                   
        alarm_weekday = bcdToDec(alarm_weekday);
    }
    
}

Fonksiyonlar bu şekilde burada. RTC_ALARM 0x80 şeklinde define edilmiş. Constrain fonksiyonu o değeri verilen aralığın dışında olduğu takdirde sınır değerler eşitliyor.

Enable alarm fonksiyonu da şöyle.
C:
void PCF85063A::enable_alarm()
{
    control_2 =      RTC_CTRL_2_DEFAULT | RTC_ALARM_AIE;     // enable interrupt
    control_2 &=     ~RTC_ALARM_AF;                                                // clear alarm flag
    
    I2C_WriteByteOneReg(I2C0,I2CADDR,RTC_CTRL_2,control_2);
}

C:
    //saat-dakika-saniye-haftanin günü-gün-ay-yil
    TSMRTC.set_time(16,20,0,Friday,14,10,22);
    //saat-dakika-saniye-gün-haftanin günü
    TSMRTC.set_alarm(16,20,15,14,Friday);

main fonksiyonu içinde de zamanı set ettim ve 15 saniye sonra için alarm kurdum. Alarm interruptı alabilmek için entegrenin INT bacağını işlemcimin INT2 bacağına bağladım ve interrupt fonksiyonu içinde de basit bir şekilde led yakıyorum. Osiloskopta INT bacağını izliyorum fakat bir şey göremiyorum. Debug modda çalıştırıp interrupt içine breakpoint koydum fakat kod interrupta gitmiyor. Şematik olarak da SDA, SCL ve INT bacaklarında 4.7k pull up dirençleri var.

pcf_alarm.png

Entegrenin PDF'inde alarm fonksiyonu şu şekilde açıklanmış. Ben kodu adım adım okuduğumda bu açıklamadaki gibi yapıldığını düşünüyorum.

Neden alarm interruptı alamıyorum acaba?
 
Öncelikle RTC nin interrupt pinini boşa al ve o şekilde interrupt geliyor mu diye bak. Belki de MCU pini, RTC nin interrupt hattını yüklüyor.
 
Öncelikle RTC nin interrupt pinini boşa al ve o şekilde interrupt geliyor mu diye bak. Belki de MCU pini, RTC nin interrupt hattını yüklüyor.

Osiloskopta şu şekilde bir kare dalga gördüm.
kare.jpeg


Benim kare dalgayı görememe sebebim büyük ihtimalle osiloskobun time div ayarından dolayıydı. Ama işin bana garip gelen kısmı şu ben programı mikroişlemciye atınca kare dalganın yükselen kenarı geliyor. Alarmı 15 saniye ilerisine kurmuştum. 15 saniye gelince kare dalganın düşen kenarını gördüm. Interrupt seçimim rising idi onu falling'e aldım ve şu an alarm alabiliyorum. Interrupt içinde de bir ledi yakabiliyorum. Entegrenin PDF'ine tekrar tekrar baktım ama bu interruptı fallingden almam gerektiğine dair bir şey göremedim malesef.
 

Çevrimiçi personel

Forum istatistikleri

Konular
5,828
Mesajlar
99,423
Üyeler
2,476
Son üye
mrmandos

Son kaynaklar

Son profil mesajları

gruptaki arkadaşlara selamlar. sıteyi bu gün fark ettim. Asansör için 2x7 segment LCD gösterge üretmek istiyorum. acaba bu sayfadaki arkadaşlardan destek alabilirmiyim. LCD nin mantık açılımı ektedir.
deneyci wrote on TA3UIS's profile.
Selam.
Amatör telsiz lisansı nasıl alınıyor?
Lisansı olmayanı forumlarına almıyorlar. :)
Bilgi alamıyoruz.
cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Back
Top