RTC alarm interrupt

Bowman

Aktif Üye
Katılım
7 Ekim 2022
Mesajlar
129
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



Kod:
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.
Kod:
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);
}

Kod:
    //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.
 

Forum istatistikleri

Konular
7,544
Mesajlar
126,363
Üyeler
3,057
Son üye
ermantml

Son kaynaklar

Son profil mesajları

Python Geliştirmeye eklediğim yapay zeka sunucusu, yeni başlayanlar için roket etkisi
Bir insanın zeka seviyesinin en kolay tesbiti, sorduğu sorulardır.
yapay zeka interneti yedi bitirdi, arama motoru kullanan, forumlara yazan kaldı mı ?
Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
Freemont2.0 posta Freemont2.0 wrote on posta's profile.
Merhabalar :)
Back
Top