DS1302 projesi (xc8 ve c18 derleyicileri için tek program)

Başlatan Gökhan BEKEN, 25 Aralık 2013, 16:04:16

Gökhan BEKEN

xc8 ve c18 derleyicileri için ayrı ayrı program yazmak yerine tek bir program ile önişlemci direktifleri kullanarak seçilen derleyiciye göre kodlar derleyiciye gönderiliyor.
Yazdığım DS1302 kütüphanesi, LCD kütüphanesi ve Delay kütüphanesini kullandım.

Normalde c18 de milisaniye veya mikrosaniye gibi özel bekleme fonksiyonları yok. Sadece saykıl olarak bekleme yapabiliyoruz ancak bu yöntem için kullanılan kristal değerine göre hesaplama yapmayı gerektiriyor ve kristal değeri değişince tekrar hesaplamayı gerektiriyor, yazdığım Delay kütüphanesi sayesinde c18 içinde DelayMs ve DelayUs şeklinde bekleme yaptırmak mümkün oluyor.
Eğer sadece xc8 kullanacaksanız o kütüphaneyi silebilirsiniz, c18 seçildiğinde devreye giriyor çünkü. LCD kütüphanesini daha önce başka bir konuda da paylaşmıştım ektra birşey yazmaya gerek duymadım, Fırat Deveci'nin HI-TECH C için yazmış olduğu bir kütüphane ancak ben c18 ve xc8 dillerine uyarladım. Asıl kütüphanemiz olan ds1302 kütüphanesi hakkında sorularınız varsa yazınız. Aşağıdaki videoda nasıl çalıştığını görebilirsiniz.

DS1302 RTC

xc8 ve c18 derleyicileri için ayrı ayrı program yazmak yerine tek bir program ile önişlemci direktifleri kullanarak seçilen derleyiciye göre kodlar derleyiciye gönderiliyor. Yazdığım DS1302 kütüphanesi, LCD kütüphanesi ve Delay kütüphanesini kullandım.


Delay.h dosyası:
#if defined __18CXX
//    #include <p18f4685.h>
    #include <delays.h>
#endif
 
#define __DELAY_C
 
#define GetSystemClock()    (4000000ul)
#define GetInstructionClock()    (GetSystemClock()/4)
 
#if !defined(GetInstructionClock)
    #error GetInstructionClock() tanimlamasi yapilmamis
#endif
#define Delay10us(us)        Delay10TCYx(((GetInstructionClock()/1000000)*(us)))
 
#define Delay1TCY()             Nop()
 
 
#if __18CXX
    void DelayMs(unsigned short int ms);
    void DelayUs(unsigned short int us);
#endif


Delay.c dosyası:
#include "Delay.h"
 
#if __18CXX
    void DelayMs(unsigned short int ms)
    {
        unsigned char i;
        while(ms--)
        {
            i=4;
            while(i--)
            {
                Delay10us(25);
            }
        }
    }
 
    void DelayUs(unsigned short int us) //word tipi
    {
        while(us--) //us degiskeni sifir olana kadar say, yani sifir olmadıgi surece say
        {
            Delay1TCY();
        }
    }
#endif



ds1302.h dosyası:
#if defined __18CXX
    #include <p18f4685.h>
    #include <delays.h>
 
#elif defined __XC8
    #include <pic18f4685.h>
    #include <xc.h> //bekleme fonksiyonlari için
    #define _XTAL_FREQ 4000000 //Bekleme fonksiyonlarini 4mhz kristal için ayarlar
 
#endif
 
 
#define TRIS_RST    TRISCbits.TRISC0
#define TRIS_SCLK   TRISCbits.TRISC1
#define TRIS_IO     TRISCbits.TRISC2
 
#define PORT_IO     PORTCbits.RC2
 
#define RST         LATCbits.LATC0
#define SCLK        LATCbits.LATC1
#define IO          LATCbits.LATC2
 
void write_byte(unsigned char Byte);
void write_ds1302(unsigned char Byte,unsigned char Data);
unsigned char read_ds1302(unsigned char Byte);
void ds1302_init(void);
unsigned char get_bcd(unsigned char Data);
unsigned char rm_bcd(unsigned char Data);
void set_datetime(unsigned char day,unsigned char mth,unsigned char year,unsigned char dow,unsigned char hr,unsigned char min, unsigned char sec);
 
unsigned char get_day(void);
unsigned char get_mth(void);
unsigned char get_year(void);
unsigned char get_dow(void);
unsigned char get_hr(void);
unsigned char get_min(void);
unsigned char get_sec(void);
 
void rtc_ram_write(unsigned char address, unsigned char data);
unsigned char rtc_ram_read(unsigned char address);


ds1302.c dosyası:
#include "ds1302.h"
 
#if defined (__18CXX)
    #include "Delay.h"
#endif
 
void iki_mikro_saniye(void)
{
    #if defined (__18CXX)
        DelayUs(2);
    #elif defined (__XC8)
        __delay_us(2);
    #endif
}
 
void write_byte(unsigned char Byte)
{
    unsigned char i;
    TRIS_IO=0;
 
    for(i=0;i<=7;++i)
    {
        IO=Byte&0x01;
        Byte>>=1;       
        SCLK=1;
        SCLK=0;
    }
}
 
void write_ds1302(unsigned char Byte,unsigned char Data)
{
    RST=1;
    write_byte(Byte);
    write_byte(Data);
    RST=0;
}
 
unsigned char read_ds1302(unsigned char Byte)
{
    unsigned char i,Data;
 
    TRIS_SCLK=0;
    TRIS_RST=0;
    RST=1;
 
    write_byte(Byte);
    TRIS_IO=1;
    Data=0;
    for(i=0;i<=6;i++)
    {
        if(PORT_IO==1){Data+=0x80;}
        Data>>=1;       
        SCLK=1;
        iki_mikro_saniye();
        SCLK=0;
        iki_mikro_saniye();
    }
    RST=0;
 
    return(Data);
}
 
 
void ds1302_init(void)
{
    unsigned char j;
    TRIS_IO=0;   
    TRIS_SCLK=0;
    TRIS_RST=0;
 
    RST=0;
    iki_mikro_saniye();
    SCLK=0;
    iki_mikro_saniye();
    write_ds1302(0x8E,0);
    write_ds1302(0x90,0xA4);
    j=read_ds1302(0x81);
    if((j & 0x80)!=0)
    {
        write_ds1302(0x80,0);
    }
}
 
unsigned char get_bcd(unsigned char Data)
{
    unsigned char NibleH,NibleL;
    NibleH=Data/10;
    NibleL=Data-(NibleH*10);
    NibleH<<=4;
    return(NibleH|NibleL);
}
unsigned char rm_bcd(unsigned char Data)
{
    unsigned char i;
    i=Data;
    Data=((i>>4)&0x0F)*10;
    Data=Data+(i&0x0F);
    return(Data);
}
 
void set_datetime(unsigned char day,unsigned char mth,unsigned char year,unsigned char dow,unsigned char hr,unsigned char min, unsigned char sec)
{
    TRIS_SCLK=0;
    TRIS_RST=0;
    write_ds1302(0x86,get_bcd(day));
    write_ds1302(0x88,get_bcd(mth));
    write_ds1302(0x8c,get_bcd(year));
    write_ds1302(0x8a,get_bcd(dow));
    write_ds1302(0x84,get_bcd(hr));
    write_ds1302(0x82,get_bcd(min));
    write_ds1302(0x80,get_bcd(sec));
}
 
unsigned char get_day(void)
{
    return(rm_bcd(read_ds1302(0x87)));
}
unsigned char get_mth(void)
{
    return(rm_bcd(read_ds1302(0x89)));
}
unsigned char get_year(void)
{
    return(rm_bcd(read_ds1302(0x8D)));
}
unsigned char get_dow(void)
{
    return(rm_bcd(read_ds1302(0x8B)));
}
unsigned char get_hr(void)
{
    return(rm_bcd(read_ds1302(0x85)));
}
unsigned char get_min(void)
{
    return(rm_bcd(read_ds1302(0x83)));
}
unsigned char get_sec(void)
{
    return(rm_bcd(read_ds1302(0x81)));
}
 
 
void rtc_ram_write(unsigned char address, unsigned char data)
{
    write_ds1302(address, data);
}
 
unsigned char rtc_ram_read(unsigned char address)
{
    return(read_ds1302(address));
}



lcd.h dosyası:
/*
* B4,B5,B6,B7 pinlerini kullanarak 4 bit iletisim kullanir.
* Cursor kapalidir.
* RW kullanilmadigi icin direk topraga baglanabilir.
*
* 2x16 LCD Kullanim Klavuzu
* lcd_init(); ile LCD'nin ilk ayarlarini yap
* lcd_clear(); ile LCD'yi sil
* lcd_yaz("deneme"); seklinde yazi yazdir.
* veri_yolla('F'); seklinde tek ascii kodu yazdir.
* lcd_gotoxy(1,13); seklinde LCD'nin istenilen yerine git.
*/
 
 
#if defined __18CXX
    #include <p18f4685.h>
    #include <delays.h>
    #include "Delay.h"
 
#elif defined __XC8
    #include <pic18f4685.h>
    #include <xc.h> //bekleme fonksiyonlari icin
    #define _XTAL_FREQ 4000000 //Bekleme fonksiyonlarini 4mhz kristal icin ayarlar
 
#endif
 
 
 
 
 
 
//#define pic_87k22_serisi
#define pic_18_serisi
/*PIN TANIMLAMALARI*/
#if defined pic_87k22_serisi
    #define rs LATDbits.LATD0
    #define rw LATDbits.LATD1
    #define e  LATDbits.LATD2
    #define rs_tris TRISDbits.TRISD0
    #define rw_tris TRISDbits.TRISD1
    #define e_tris  TRISDbits.TRISD2
 
#elif defined pic_18_serisi
    #define rs LATDbits.LATD0
    #define rw LATDbits.LATD1
    #define e  LATDbits.LATD2
    #define rs_tris TRISDbits.RD0
    #define rw_tris TRISDbits.RD1
    #define e_tris  TRISDbits.RD2
 
#endif
 
#define lcd_port LATB
#define lcd_tris TRISBbits
////////////////////////////////////////////
 
 
/* LCD'de kullanilan komutlarin tanimlamasi*/
#define Sil 1 // Ekrani temizler
#define BasaDon 2 // Imleci sol ust koseye getirir
#define SolaYaz 4 // Imlecin belirttigi adres azalarak gider
#define SagaYaz 6 // Imlecin belirttigi adres artarak gider
#define ImlecGizle 12 // Gostergeyi ac, kursor gorunmesin
#define ImlecAltta 14 // Yanip sonen blok kursor
#define ImlecYanSon 15 // Yanip sonen blok kursor
#define ImlecGeri 16 // Kursoru bir karakter geri kaydir
#define KaydirSaga 24 // Gostergeyi bir karakter saga kaydir
#define KaydirSola 28 // Gostergeyi bir karakter sola kaydir
#define EkraniKapat 8 // Gostergeyi kapat (veriler silinmez)
#define BirinciSatir 128 // LCD'nin ilk satir baslangic adresi
// (DDRAM adres)
#define IkinciSatir 192 // ikinci satirin baslangic adresi
#define KarakUretAdres 64 // Karakter ureteci adresini belirle
// (CGRAM adres)
/* LCD'de Kullanilan Fonksiyon Secimi */
#define CiftSatir8Bit 56 // 8 bit ara birim, 2 satir, 5*7 piksel
#define TekSatir8Bit 48 // 8 bit ara birim, 1 satir, 5*7 piksel
#define CiftSatir4Bit 40 // 4 bit ara birim, 2 satir, 5*7 piksel
#define TekSatir4Bit 32 // 4 bit ara birim, 1 satir, 5*7 piksel
extern void veri_yolla(unsigned char);
extern void lcd_clear(void);
extern void lcd_yaz(const char *s);
extern void lcd_gotoxy(unsigned char x, unsigned char y);
extern void lcd_init(void);
extern void lcd_komut(unsigned char c);


lcd.c dosyası:
#include "lcd.h" // lcd.h dosyasi tanimlanip, degerler aliniyor
 
void lcd_busy(void)
{
    #if defined __18CXX
        DelayUs(250);
    #elif defined __XC8
        __delay_us(100);__delay_us(100);__delay_us(50);  //250 mikrosaniyelik bekleme
    #endif
}
 
void lcd_komut(unsigned char c) // Komut g�nderme fonksiyonu
{
    rw=0; // LCD'ye yazma yapilacak
    rs=0; // LCD'ye komut gonderilecek
    e=1; // Dusen kenar tetikleme oldugu icin E once 1
    lcd_port = ( c & 0xF0 ); // Yuksek degerlikli bitler gonderiliyor
    e=0; // E, 0 yapiliyor
    lcd_busy(); //Belirli sure bekleniyor
    e=1; // E, 1 yapiliyor
    lcd_port = ( (c & 0x0F)<<4 ); // Dusuk degerlikli bitler gonderiliyor
    e=0; // E, 0 yapiliyor
    lcd_busy(); // Belirli bir sure bekleniyor
}
 
void veri_yolla(unsigned char c)
{
    rw=0;
    rs=1; // Komut yolladan tek farki, RS'nin 1 olmasi
    e=1;
    lcd_port = ( c & 0xF0 );
    e=0;
    lcd_busy();
    e=1;
    lcd_port = ( (c & 0x0F)<<4 );
    e=0;
    lcd_busy();
}
 
void lcd_clear(void) // LCD siliniyor
{
    lcd_komut(0x1);
    #if defined __18CXX
        DelayMs(2);
    #elif defined __XC8
        __delay_ms(2);
    #endif
}
 
void lcd_yaz(const char * s) // LCD'ye string ifade g�nderiliyor
{
    lcd_busy();
    while(*s)
    veri_yolla(*s++);
}
 
void lcd_gotoxy(unsigned char x,unsigned char y) //LCD'nin belli //bolgesine gidiliyor
{
    if(x==1)
    lcd_komut(0x80+((y-1)%16));
    else
    lcd_komut(0xC0+((y-1)%16));
}
 
void lcd_init() // LCD ilk y�kleme ayarlari yapiliyor
{
 
 
    #if defined pic_87k22_serisi
    lcd_tris.TRISB4=0;
    lcd_tris.TRISB5=0;
    lcd_tris.TRISB6=0;
    lcd_tris.TRISB7=0;
    #else
    lcd_tris.RB4=0;
    lcd_tris.RB5=0;
    lcd_tris.RB6=0;
    lcd_tris.RB7=0;
    #endif
 
 
    rs_tris=0;
    rw_tris=0;
    e_tris=0;
 
 
 
    rs = 0;
    e = 0;
    rw = 0;
    #if defined __18CXX
        DelayMs(15);
    #elif defined xc8
        __delay_ms(15);
    #endif
    e=1;
    lcd_komut(0x02);
    #if defined __18CXX
        DelayMs(2);
    #elif defined xc8
        __delay_ms(2);
    #endif
    lcd_komut(CiftSatir4Bit);
    lcd_komut(SagaYaz);
    lcd_komut(ImlecGizle);
    lcd_clear();
    lcd_komut(BirinciSatir);
}




main.h dosyası:
/*
 * File:   main.h
 * Created on 20 Aralik 2013 Pazartesi, 15:32
 * yazan: M. Gokhan BEKEN
 * 18f4685 kullanilmistir, ozel bir sebebi yoktur
 * degerleri LCD ile gorecegiz
 */
 
 
#if defined __18CXX
    #include <p18f4685.h>
    #include <delays.h>
    #include <stdio.h> //sprintf için gerekli
    #include "lcd.h" // LCD kütüphanesi cagiriliyor
    #include "ds1302.h" //RTC kutuphanesi cagiriliyor
    #include "Delay.h" //kendi delay kutuphanemiz
#elif defined __XC8
    #include <pic18f4685.h>
    #include <xc.h> //bekleme fonksiyonlari icin
    #include <stdio.h> //sprintf icin gerekli
    #include "lcd.h" // LCD kutuphanesi cagiriliyor
    #include "ds1302.h" //RTC kutuphanesi cagiriliyor
    #define _XTAL_FREQ 4000000 //Bekleme fonksiyonlarini 4mhz kristal icin ayarlar
#endif
 
#pragma config OSC = HS, WDT = OFF, LVP = OFF


main.c dosyası:
/*
 * Created on 20 Aralik 2013 Pazartesi, 15:32
 * yazan: M. Gökhan BEKEN
 * 18f4685 kullanilmistir, ozel bir sebebi yoktur
 * degerleri LCD ile gorecegiz
 */
 
 
#include "main.h"
 
void main(void)
{
    unsigned char s1[16]="";
    unsigned char s2[16]="";
    unsigned char oku_eeprom[16]="";
 
    unsigned char gun=0,ay=0,yil=0,hafta=0,saat=0,dakika=0,saniye=0;
    unsigned char gun_hafta[10]="";
 
    lcd_init(); // LCD ilk ayarlar yap?l?yor
     
    #if defined __18CXX
        sprintf(s1,"Derleyici:");
        sprintf(s2,"C18");
    #elif defined __XC8
        sprintf(s1,"Derleyici:");
        sprintf(s2,"XC8");
    #endif
     
    lcd_clear();
    lcd_gotoxy(1,1); //birinci satirin birinci sutununa gec
    lcd_yaz(s1);
    lcd_gotoxy(2,1); // ikinci satirin birinci sutununa gec
    lcd_yaz(s2);
     
    #if defined __18CXX
        DelayMs(1000);
    #elif defined __XC8
        __delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);
        __delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);
    #endif
 
 
 
 
 
 
 
 
 
 
 
    TRISAbits.RA0=0; //a0 daki saniye ledi için
 
    ds1302_init(); // ds1302 ilk ayarları yapılıyor
 
     
 
 
    //31.12.2009 PerĢembe, 23:59:50'a ayarlanıyor
    set_datetime(31,12,9,5,23,59,50);
 
    //İsmimizi eeproma yazıyoruz, 1 kere yazmamız yeterlidir, her çalıştırmada yazmaya gerek yok.
    rtc_ram_write(0xC0, 'G');
    rtc_ram_write(0xC2, '.');
    rtc_ram_write(0xC4, 'B');
    rtc_ram_write(0xC6, 'E');
    rtc_ram_write(0xC8, 'K');
    rtc_ram_write(0xCA, 'E');
    rtc_ram_write(0xCC, 'N');
    //ds1302nin ram'i 31byte'tır C1h-C0h adreslerinden FDh-FCh adreslerine kadar kullanabiliriz
 
 
    /*ilk adrese 0xC0 ile yazım yapılabilirken, 0xC1 ile okuma yapılabilmektedir. Her zaman 1 fazlasını oku*/
    oku_eeprom[0]=(rtc_ram_read(0xC1));
    oku_eeprom[1]=(rtc_ram_read(0xC3));
    oku_eeprom[2]=(rtc_ram_read(0xC5));
    oku_eeprom[3]=(rtc_ram_read(0xC7));
    oku_eeprom[4]=(rtc_ram_read(0xC9));
    oku_eeprom[5]=(rtc_ram_read(0xCB));
    oku_eeprom[6]=(rtc_ram_read(0xCD));
 
    sprintf(s1,"RTC EEPROM:");
    sprintf(s2,"%s",oku_eeprom);
    lcd_clear();
    lcd_gotoxy(1,1); //birinci satırın birinci sutununa geç
    lcd_yaz(s1);
    lcd_gotoxy(2,1); // ikinci satırın birinci sutununa geç
    lcd_yaz(s2);
 
    #if defined __18CXX
        DelayMs(1000);
    #elif defined __XC8
        __delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);
        __delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);__delay_ms(100);
    #endif
 
 
    while(1)
    {
        while(saniye==get_sec()) //saniye degisene kadar bekle
        {
            //sürekli sorgu yapmak yerine 100ms de bir sorgu yapmak için bekleme koyduk
            #if defined __18CXX
                DelayMs(100);
            #elif defined __XC8
                __delay_ms(100);
            #endif
        }
        LATAbits.LATA0^=1; //a0 pinini tersle
 
        gun=get_day();     
        ay=get_mth();      
        yil=get_year();    
        hafta=get_dow();   
        saat=get_hr();     
        dakika=get_min();  
        saniye=get_sec();  
 
        switch(hafta)
        {
            case 1: sprintf(gun_hafta,"PAZR");break;
            case 2: sprintf(gun_hafta,"PZTS");break;
            case 3: sprintf(gun_hafta,"SALI");break;
            case 4: sprintf(gun_hafta,"CRSM");break;
            case 5: sprintf(gun_hafta,"PERS");break;
            case 6: sprintf(gun_hafta,"CUMA");break;
            case 7: sprintf(gun_hafta,"CMTS");break;
        }
 
        if(yil<10)sprintf(s1,"%d/%d/200%d %s",gun,ay,yil,gun_hafta); //10dan küçükse fazladan 1 sıfır attık
        else sprintf(s1,"%d/%d/20%d %s  ",gun,ay,yil,gun_hafta);
 
        sprintf(s2,"%d:%d:%d   ",saat,dakika,saniye);
 
//        lcd_clear();
        lcd_gotoxy(1,1); //birinci satırın birinci sutununa geç
        lcd_yaz(s1);
        lcd_gotoxy(2,1); //ikinci satırın birinci sutununa geç
        lcd_yaz(s2);
 
    }       
 
    while(1);
}


Kaynak:  http://gokhanbeken.com/ds1302-projesi-xc8-ve-c18-derleyicileri-icin-tek-program
Özel mesaj okumuyorum, lütfen göndermeyin.