20 Temmuz 2016 Çarşamba

PIC18F452 CCS C - DS1307 Zaman Modülü Uygulaması



Bu yazımda DS1307 entegreli RTC modülümüzle I2C haberleşmesini kullanarak gün/tarih/saat bilgilerini okuyup, bu bilgileri PIC18F452 mikrodenetleyicimizle LCD'de göstereceğiz. 


Modülün sağdaki resimde görüldüğü gibi iki tarafında da header padleri bulunmakta. Ben sadece sol taraftaki padleri kullandım. İsterseniz sol üste DS18b20 modülünü de takarak sıcaklık değeri okuyabiliyorsunuz. Ben sadece zaman okudum.






I2C Haberleşmesi ( Inter-Integrated Circuit)


Kısaca bahsetmek gerekirse I2C , PHILIPS firmasının kendi ürünlerinde kullanmak üzere geliştirdiği,veri giriş-çıkış hızının çok önemli olmadığı ve pin kullanımını azami sayıya düşüren bir haberleşme protokolüdür. Haberleşmede iki uç kullanılır.Bunlar;

SDA - Seri Veri Giriş-Çıkış
SCL - Seri Saat Sinyali ( Clock )

Master-Slave ilkesine göre iş yapan bu protokolde, özetle master cihaz öncelikle SDA hattından "START" bilgisi gönderir, iletişim kuracağı cihazın adresini yazar ve adresi yazılan slave , "STOP" bilgisi gelene kadar master ile haberleşme kontağında bulunur.


Detaylı bilgi için aşağıdaki siteleri ziyaret edebilirsiniz.

http://ramazansural.blogspot.com.tr/2010/11/i2c-haberlesme-protokolu.html
https://elkitabim.com/tag/i2c-haberlesmesi/

Kullanacağımız kütüphaneye göre modülümüzün adresi 0xD0 olacak.
Yazılımımızda öncelikle gün,saat,dakika,saniye,gün,ay,yıl ibarelerini belirlememiz gerekiyor. Bunları belirledikten sonra zaman işlemeye başlıyor.

SCL ve SDA uçlarını PIC'te bulunan aynı isimdeki uçlara yukarıda şemada görüldüğü gibi Pull-Up direnci takarak bağlıyoruz.

DS1307.C Driver Kodları



///////////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                           ///
///                     Driver for Real Time Clock                                   ///
///                     modified by Redpic 08/2006                                   ///
///                  http://picmania.garcia-cuervo.com                               ///
///                                                                                  ///
/// void ds1307_init(val)                                                            ///
///                  - Enable oscillator without clearing the seconds register       ///
///                    used when PIC loses power and DS1307 run from 3V BAT          ///
///                  - Config Control Register with next parameters:                 ///
///                     DS1307_ALL_DISABLED          All disabled                    ///
///                     DS1307_OUT_ON_DISABLED_HIHG  Out to Hight on Disable Out     ///
///                     DS1307_OUT_ENABLED           Out Enabled                     ///
///                     DS1307_OUT_1_HZ              Freq. Out to 1 Hz               ///
///                     DS1307_OUT_4_KHZ             Freq. Out to 4.096 Khz          ///
///                     DS1307_OUT_8_KHZ             Freq. Out to 8.192 Khz          ///
///                     DS1307_OUT_32_KHZ            Freq. Out to 32.768 Khz         ///
///                                                                                  ///
///                     Example init:                                                ///
///                     ds1307_init(DS1307_ALL_DISABLED);                            ///
///                     ds1307_init(DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);           ///
///                                                                                  ///
/// void ds1307_set_date_time(day,mth,year,dow,hour,min,sec) - Set the date/time     ///
///                                                                                  ///
/// void ds1307_get_date(day,mth,year,dow)                   - Get the date          ///
///                                                                                  ///
/// void ds1307_get_time(hr,min,sec)                         - Get the time          ///
///                                                                                  ///
/// char ds1307_read_nvram_byte(char addr)                   - Read byte in address  ///
///                                                                                  ///
/// void ds1307_write_nvram_byte(char addr, char value)      - Write byte in address ///
///                                                                                  ///
/// void ds1307_get_day_of_week(char* ptr)                   - Get string Day Of Week///
///                                                                                  ///
/// If defined USE_INTERRUPTS all functions disable Global Interrupts on starts and  ///
///                           enable Global on ends else usar can do it hiself       ///
///                                                                                  ///
///////////////////////////////////////////////////////////////////////////////////////

#ifndef RTC_SDA
#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3
#endif

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)

#define DS1307_ALL_DISABLED         0b00000000 // All disabled
#define DS1307_OUT_ON_DISABLED_HIHG 0b10000000 // Out to Hight on Disable Out
#define DS1307_OUT_ENABLED          0b00010000 // Out Enabled
#define DS1307_OUT_1_HZ             0b00000000 // Freq. Out to 1 Hz
#define DS1307_OUT_4_KHZ            0b00000001 // Freq. Out to 4.096 Khz
#define DS1307_OUT_8_KHZ            0b00000010 // Freq. Out to 8.192 Khz
#define DS1307_OUT_32_KHZ           0b00000011 // Freq. Out to 32.768 Khz

#define Start_user_address_nvram    0x08
#define End_user_address_nvram      0x3f

char days_of_week[7][11]={"Pzt  ","Sali ","Cars ","Pers ","Cuma ","Cmt  ","Pazar"};

byte ds1307_bin2bcd(byte binary_value);
byte ds1307_bcd2bin(byte bcd_value);

void ds1307_init(int val){

   byte seconds = 0;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_start();
   i2c_write(0xD1);
   seconds = ds1307_bcd2bin(i2c_read(0));
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_write(ds1307_bin2bcd(seconds));
   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x07);
   i2c_write(val);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_set_date_time(byte day, byte mth, byte year, byte dow, byte hr, byte min, byte sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_write(ds1307_bin2bcd(sec));
  i2c_write(ds1307_bin2bcd(min));
  i2c_write(ds1307_bin2bcd(hr));
  i2c_write(ds1307_bin2bcd(dow));
  i2c_write(ds1307_bin2bcd(day));
  i2c_write(ds1307_bin2bcd(mth));
  i2c_write(ds1307_bin2bcd(year));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_date(byte &day, byte &mth, byte &year, byte &dow){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);
  i2c_start();
  i2c_write(0xD1);
  dow  = ds1307_bcd2bin(i2c_read() & 0x7f);
  day  = ds1307_bcd2bin(i2c_read() & 0x3f);
  mth  = ds1307_bcd2bin(i2c_read() & 0x1f);
  year = ds1307_bcd2bin(i2c_read(0));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_time(byte &hr, byte &min, byte &sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_start();
  i2c_write(0xD1);
  sec = ds1307_bcd2bin(i2c_read() & 0x7f);
  min = ds1307_bcd2bin(i2c_read() & 0x7f);
  hr  = ds1307_bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}


char ds1307_read_nvram_byte(char addr){

   char retval;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);

   i2c_start();
   i2c_write(0xD1);
   retval = i2c_read(0);
   i2c_stop();

   return(retval);

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_write_nvram_byte(char addr, char value){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);
   i2c_write(value);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_day_of_week(char* ptr){

   byte lday;
   byte lmonth;
   byte lyr;
   byte ldow;
   ds1307_get_date(lday,lmonth,lyr,ldow);
   sprintf(ptr,"%s",days_of_week[ldow]);
}

///////////////////////////////////////////////////////////////////////////////

byte ds1307_bin2bcd(byte binary_value){

  byte temp;
  byte retval;

  temp = binary_value;
  retval = 0;
  while(1){
    if(temp >= 10){
      temp -= 10;
      retval += 0x10;
    }else{
      retval += temp;
      break;
    }
  }
  return(retval);
}

byte ds1307_bcd2bin(byte bcd_value){

  byte temp;

  temp = bcd_value;
  temp >>= 1;
  temp &= 0x78;
  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}

///////////////////////////////////////////////////////////////////////////////


Bu kodları not defterine ds1307.c ismiyle kaydedip projemizin bulunduğu klasöre atıyoruz. Kaynak kodlarımız;


#include <18F452.h>
#device adc=10

#FUSES NOWDT                  //No Watch Dog Timer
#FUSES HS                     //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                  //No Power Up Timer
#FUSES NOPROTECT              //Code not protected from reading
#FUSES NODEBUG                //No Debug mode for ICD
#FUSES NOBROWNOUT             //No brownout reset
#FUSES NOLVP                  //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                  //No EE protection
#FUSES NOWRT                  //Program memory not write protected
#FUSES RESERVED               //Used to set the reserved FUSE bits

#use delay(clock=20000000)

#include <ds1307.c>
#include  <flexible.c>

int sec;
int min;
int hrs;
int  day;
int  month;
int  yr;
int dow;
char tarih[4];

void main(){
   lcd_init();
   ds1307_set_date_time(19,7,16,1,13,22,40);  // Şu anki tarih. Gün/Ay/Yıl ve Saat/Dakika,Saniye
while(true){
      ds1307_get_date (day, month, yr, dow); //Tam Tarihi Oku
      ds1307_get_time (hrs, min, sec);   /// Tam Saati oku
      ds1307_get_day_of_week(tarih);
      lcd_gotoxy(1,1);
      printf(lcd_putc,"%s %02u/%02u/20%02u",tarih,day,month,yr);
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Saat: %02u:%02u:%02u",hrs, min, sec);
      delay_ms(200); 
  }
}

Kaynak kodlarını kendi LCD kütüphanenize göre düzenlemeyi unutmayın.



Fotoğrafı çekerken dikkat etmemişim, yazılımda düzelttim sonradan, Tarih yerine Saat yazacak yukarıda size verdiğim kodlara göre.




4 yorum:

  1. Helal be kardeşim. Çok güzel çalışmalar yapmışsın.A. Razı olsun. Mühendis gibi mühendissin.

    YanıtlaSil
  2. flexible.c klasör nereden bulabiliriz. Klasör olmadan derleme yapmıyor.

    YanıtlaSil
  3. Merhabalar
    Yazılarınız çok açıklayıcı teşekkür ederim, pic16f876 ile PCA9685 pwm entegresini kullanıp MG995 servo motoru sürmek istiyorum fakat çözemedim, bir ödev için maket araba kumandası yaptım alıcı verici kısmını yapıp yaptıgım kumandayla normal 4 adet dc motoru kontrol edebiliyorum fakat servo ve PCA9685 entegresini yapamadım, bu konuda burada bir örnek kod yayınlamanız mümkünmü çok teşekkürler

    YanıtlaSil