ds1307 RTC modülü

Başlatan PICaso, 09 Temmuz 2019, 11:11:43

PICaso

Değerli arkadaşlar,
PIC18F4520 ile ds1307 RTC modülü kullanarak saat uygulaması yapıyorum fakat enerji kesildiğinde saat program da başlattığım saatten yeniden başlıyor. Yazılım kısmında hata yaptığımı düşünüyorum. Desteklerinizi bekliyorum.
İyi çalışmalar.
#define _XTAL_FREQ 20000000

#define RS RB2
#define EN RB3
#define D4 RB4
#define D5 RB5
#define D6 RB6
#define D7 RB7

#include <xc.h>
#include "lcd.h";
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>


#pragma config OSC = HS        // Oscillator Selection bits HS
#pragma config FCMEN = OFF       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = OFF        // Internal/External Oscillator Switchover bit (Oscillator Switchover mode enabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF       // Brown-out Reset Enable bits (Brown-out Reset enabled and controlled by software (SBOREN is enabled))
#pragma config BORV = 3         // Brown Out Reset Voltage bits (Minimum setting)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF      // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks)




#define RTC_WRITE_ADDR   (0xD0)
#define RTC_READ_ADDR    (0xD1)

uint8_t print_buffer[256] = {0};

typedef struct{
    
    uint8_t secL:4;
    uint8_t secH:3;
    uint8_t hold_clock:1;
    
    uint8_t minL:4;
    uint8_t minH:3;
    uint8_t rfu1:1;
    
    uint8_t hourL:4;
    uint8_t hourH:2;
    uint8_t hour_mode:1;
    uint8_t rfu2:1;
    
    uint8_t day:3;
    uint8_t rfu3:5;
    
    uint8_t dateL:4;
    uint8_t dateH:2;
    uint8_t rfu4:2;
    
    uint8_t monthL:4;
    uint8_t monthH:1;
    uint8_t rfu5:3;
    
    uint8_t yearL:4;
    uint8_t yearH:4;

}rtc_time_read;

rtc_time_read rtc_data;

void i2c_is_idle(void){
    while((SSPCON2 & 0x1F) || (SSPSTAT & 0x04) );
}

void i2c_start(void){
    i2c_is_idle();
    SSPCON2bits.SEN = 1;
}

void i2c_rep_start(void){
    i2c_is_idle();
    SSPCON2bits.RSEN = 1;
}

void i2c_stop(void){
    i2c_is_idle();
    SSPCON2bits.PEN = 1;
}

void i2c_write(uint8_t i2c_data){
    i2c_is_idle();
    SSPBUF = i2c_data;
    while(SSPSTATbits.BF != 0);
    while(SSPCON2bits.ACKSTAT != 0);
}

uint8_t i2c_read(uint8_t ack){
    uint8_t recieve =0;
    i2c_is_idle();
    SSPCON2bits.RCEN = 1;
    while(SSPSTATbits.BF != 1);
    recieve = SSPBUF;
    SSPCON2bits.ACKEN = ack;
    return recieve;
}

void i2c_init(void){
    TRISCbits.RC3 = 1;
    TRISCbits.RC4 = 1;
    
    SSPSTATbits.SMP = 1;
    SSPSTATbits.CKE = 0;
    SSPCON1bits.SSPM = 0x08;
    SSPADD = 49;                
    SSPCON1bits.SSPEN = 1;
    
}

int main() {
                        char print_buffer [256];
                      // char print_buffer [16];
                       //char s[16];
    
    uint8_t rtc_buff[7] = {0};
   
    TRISB = 0x00; //LCD BAGLANTILARI
    Lcd_Init();
    
    memset(&rtc_data,0,sizeof(rtc_data));
                                               
    rtc_data.secH = 0;
    rtc_data.secH = 0;
    
    rtc_data.minL = 6;
    rtc_data.minH = 4;
    
    rtc_data.hourL = 8;
    rtc_data.hourH = 0;
    
    rtc_data.day = 7;
    
    rtc_data.dateL = 9;
    rtc_data.dateH = 0;
    
    rtc_data.monthL = 7;
    rtc_data.monthH = 0;
    
    rtc_data.yearL = 9;
    rtc_data.yearH = 1;
    
 memcpy(rtc_buff,&rtc_data,sizeof(rtc_data));    
                                 
    i2c_init();
    i2c_start();
    i2c_write(RTC_WRITE_ADDR);
    i2c_write(0x00);
    i2c_write(rtc_buff[0]);
    i2c_write(rtc_buff[1]);
    i2c_write(rtc_buff[2]);
    i2c_write(rtc_buff[3]);
    i2c_write(rtc_buff[4]);
    i2c_write(rtc_buff[5]);
    i2c_write(rtc_buff[6]);
    i2c_stop();
     
    while(1){      
        i2c_start();
        i2c_write(RTC_WRITE_ADDR);
        i2c_write(0x00);
        i2c_rep_start();
        i2c_write(RTC_READ_ADDR);       
        rtc_buff[0] = i2c_read(1);
        rtc_buff[1] = i2c_read(1);
        rtc_buff[2] = i2c_read(1);
        rtc_buff[3] = i2c_read(1);
        rtc_buff[4] = i2c_read(1);
        rtc_buff[5] = i2c_read(1);
        rtc_buff[6] = i2c_read(0);
        i2c_stop();
      
        memcpy(&rtc_data,rtc_buff,sizeof(rtc_data));
        
        sprintf(print_buffer,"%d%d/%d%d/20%d%d",
     
                rtc_data.dateH,
                rtc_data.dateL,
                rtc_data.monthH,
                rtc_data.monthL,
                rtc_data.yearH,
                rtc_data.yearL
                );
                Lcd_Set_Cursor(1,1);
                Lcd_Write_String(print_buffer);
        
        sprintf(print_buffer,"%d%d:%d%d:%d%d",
     
                rtc_data.hourH,
                rtc_data.hourL,
                rtc_data.minH,
                rtc_data.minL,
                rtc_data.secH,
                rtc_data.secL
                );  
                Lcd_Set_Cursor(2,1);
                Lcd_Write_String(print_buffer);

        __delay_ms(500);   
    } 
     return 0;
}
 

mur@t

PIC'e her enerji verdiğinizde saat/tarih bilgilerini set ediyor olabilir misiniz?

Tagli

Anladığım kadarıyla, işlemci çalışmaya başladığında RTC'ye varsayılan tarih saat değerini yüklüyorsun. Bu durumda dediğin şeyin olması çok normal. O kısmı koddan kaldırmalısın.

Veya şu da yapılabilir: DS1307'nin saati aç kapa yapan bir biti vardı diye kalmış aklımda. Açılışta onu okursun. Saat çalışıyorsa hiç dokunmazsın, çalışmıyorsa varsayılan tarih ve saati yüklersin.

Sonuçta bir şekilde dışarıdan saat ayarlama fonksiyonu eklemen gerek. Bu belki encoder switch ile olur, elle ayarlanır, belki dr seri porttan gelen bir komut ile olur, artık senin tercihine kalmış.
Gökçe Tağlıoğlu

PICaso

Alıntı yapılan: mur@t - 09 Temmuz 2019, 11:36:17PIC'e her enerji verdiğinizde saat/tarih bilgilerini set ediyor olabilir misiniz?
Evet bu kısımda öyle yapıyorum.
memset(&rtc_data,0,sizeof(rtc_data));
                                               
    rtc_data.secH = 0;
    rtc_data.secH = 0;
   
    rtc_data.minL = 6;
    rtc_data.minH = 4;
   
    rtc_data.hourL = 8;
    rtc_data.hourH = 0;
   
    rtc_data.day = 7;
   
    rtc_data.dateL = 9;
    rtc_data.dateH = 0;
   
    rtc_data.monthL = 7;
    rtc_data.monthH = 0;
   
    rtc_data.yearL = 9;
    rtc_data.yearH = 1;

fide

Saat ayarlamaya bir defa yaptıktan sonra bu kodu kapat. Enerji kesilince pic resetleniyor ve her açılışta saati yeniden set ediyor. @Tagli'nin bahsettiği de bu
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

PICaso

#5
Alıntı yapılan: Tagli - 09 Temmuz 2019, 11:40:28Anladığım kadarıyla, işlemci çalışmaya başladığında RTC'ye varsayılan tarih saat değerini yüklüyorsun. Bu durumda dediğin şeyin olması çok normal. O kısmı koddan kaldırmalısın.

Veya şu da yapılabilir: DS1307'nin saati aç kapa yapan bir biti vardı diye kalmış aklımda. Açılışta onu okursun. Saat çalışıyorsa hiç dokunmazsın, çalışmıyorsa varsayılan tarih ve saati yüklersin.


Öncelikle bu kısımlar halletmeye çalıştım. Dediğiniz gibi varsayılan saat ayarlayacak şekilde değişiklik yaptım. Varsayılan saat doğru çalışıyor. Enerjiyi kesip verince ekrana 00/00/2000  00:00:00 şeklinde veri geliyor. Ne yapmam gerekir bu durumda?

Tagli

Öyle bir kod yazmalısın ki, varsayılan saati ayarlayan kısım sadece bir kez çalışmalı. Bunun için de önceki mesajımda bahsetmiş olduğum yöntemi kullanabilirsin. Normalde DS1307 ilk elektrik aldığında saniye register'ının (0x00 adresindeki) 7. biti olan CH (clock halt) 1'dir. Bu durumda saat çalışmaz. Anladığım kadarıyla sen saniyeyi yazarken bunu da farkında olmadan 0 yapıyorsun ve saat çalışmaya başlıyor. Bu zaten olması gereken şey. Ama ilk açılışta bu biti okumalı ve eğer 0 ise saatin zaten çalıştığı sonucuna varıp, varsayılan saat değerlerini çipe yollamaktan kaçınmalısın.
Gökçe Tağlıoğlu

M_B

#7
DS1307 'nin 3 nolu ayağına battery (CR2032 ) takarsan enerji kesilip geldiğinde saat kaldığı yerden devam eder.
Hazır modul kullanıyorsanız da Pili kontrol edin. Bitmiş olabilir.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

PICaso

#8
Alıntı yapılan: M_B - 09 Temmuz 2019, 15:43:20DS1307 'nin 3 nolu ayağına battery (CR2032 ) takarsan enerji kesilip geldiğinde saat kaldığı yerden devam eder.
Hazır modul kullanıyorsanız da Pili kontrol edin. Bitmiş olabilir.
Modül kullanıyorum. Pil 2.8 V olarak ölçtüm.

PICaso

Alıntı yapılan: Tagli - 09 Temmuz 2019, 15:15:00Öyle bir kod yazmalısın ki, varsayılan saati ayarlayan kısım sadece bir kez çalışmalı. Bunun için de önceki mesajımda bahsetmiş olduğum yöntemi kullanabilirsin. Normalde DS1307 ilk elektrik aldığında saniye register'ının (0x00 adresindeki) 7. biti olan CH (clock halt) 1'dir. Bu durumda saat çalışmaz. Anladığım kadarıyla sen saniyeyi yazarken bunu da farkında olmadan 0 yapıyorsun ve saat çalışmaya başlıyor. Bu zaten olması gereken şey. Ama ilk açılışta bu biti okumalı ve eğer 0 ise saatin zaten çalıştığı sonucuna varıp, varsayılan saat değerlerini çipe yollamaktan kaçınmalısın.
SORUN ÇÖZÜLDÜ
Yardımcı olan herkese çok teşekkür ediyorum.Varsayılan saat için buton şartı koydum. Butona basılıyken enerji veriyorum varsayılan saat yükleniyor. Daha sonra ki enerji vermeler de butonu kullanmıyorum. @Tagli hocanın da bahsettiği CH bitinin sorunun çözümüne büyük katkısı olmuştur.
İyi günler.