RTC alarm interrupt

Bowman

Aktif Üye
Katılım
7 Ekim 2022
Mesajlar
112
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
6,956
Mesajlar
118,801
Üyeler
2,825
Son üye
karahanli7

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top