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.
Helal be kardeşim. Çok güzel çalışmalar yapmışsın.A. Razı olsun. Mühendis gibi mühendissin.
YanıtlaSilflexible.c klasör nereden bulabiliriz. Klasör olmadan derleme yapmıyor.
YanıtlaSilO LCD tanım klasörü LCD.c gibi
SilMerhabalar
YanıtlaSilYazı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