PCF8583 için Sürücü Programı

Bu sayfada PCF8583 gerçek zaman entegresi için sürücü programı verilmiştir.


Bu entegre yıl bilgisini tutacak 8 bitlik yazmacı olmaması ve yedek pil için besleme bacağına sahip olmadığından saat devreleri için çok ideal değildir. DS1307 veya sürücüsü ccs’de hazır olan DS1302 entegresi uygulamalarınızda daha yararlı olabilir.
Bu sürücü dosyasında yıl bilgisini tutmak için NVRAM’den yazılımsal olarak faydalanılmıştır. Her 3 yıılda bir yıl bilgisi okunduğu sürece sıkıntı olmayacaktır.

Tasarımında bu entegreyi kullanmak isteyenler için örnek uygulama bağlantıları, programı ve sürücü yazılımı aşağıda verilmiştir.

Örnek Uygulama programı:

#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)</pre>

#include <ctype.h>
#include <PCF8583.c>

// Bu uygulama programında tarih zaman bilgileri
// seri porttan gösterilir veya değiştirilebilir

void main()
{
char c;
char weekday[10];
date_time_t dt;

PCF8583_init();

printf(”Ornek tarih ve zaman bilgileri\n\r”);
printf(”23/12/06 23:59:50 (Pazar) yazilsin mi ? (Y/N)\n\r”);

while(1)
{
c = getc(); // Wait for user to press a key
c = toupper(c);

if(c == ‘Y’)
{
dt.month = 12; // Aralık
dt.day = 31; // 31
dt.year = 07; // 2007
dt.hours = 23; // 23 saat
dt.minutes = 59; // 59 dakika
dt.seconds = 50; // 50 saniye
dt.weekday = 0; // 0 = Pazar, 1 = Pzartesi, vs.

PCF8583_set_datetime(&dt);
printf(”\n\r”);
printf(”Yani tarih ve zaman bilgieri yazildi.\n\r”);
printf(”2008′e gecise bakiniz \r”);
break;
}

if(c == ‘N’)
break;
}

printf(”\n\r”);
printf(” Tarih zaman bilgileri okunuyor\n\r”);

// Tarih ve zaman bilgileri birer saniye aralıklarla gösterilir
.
while(1)
{
delay_ms(1000);

PCF8583_read_datetime(&dt);

strcpy(weekday, weekday_names[dt.weekday]);

printf(”%s, %u/%u/%02u, %u:%02u:%02u\n\r”,
weekday, dt.day, dt.month, dt.year,
dt.hours, dt.minutes, dt.seconds);
}

}

Sürücü Dosyası



//Bu kodları PCF8583.C olarak kaydediniz
//Yazar: PCM Programmer 
#ifndef PCF8583_SDA
#define PCF8583_SDA  PIN_C4
#define PCF8583_SCL  PIN_C3
#endif

 
#use i2c(master, sda=PCF8583_SDA, scl=PCF8583_SCL)

 
#ifndef PCF8583_WRITE_ADDRESS
#define PCF8583_WRITE_ADDRESS 0xA0
#define PCF8583_READ_ADDRESS  0xA1
#endif

 
// Register adresleri
#define PCF8583_CTRL_STATUS_REG    0×00
#define PCF8583_100S_REG           0×01
#define PCF8583_SECONDS_REG        0×02
#define PCF8583_MINUTES_REG        0×03
#define PCF8583_HOURS_REG          0×04
#define PCF8583_DATE_REG           0×05
#define PCF8583_MONTHS_REG         0×06
#define PCF8583_TIMER_REG          0×07

 
#define PCF8583_ALARM_CONTROL_REG  0×08
#define PCF8583_ALARM_100S_REG     0×09
#define PCF8583_ALARM_SECS_REG     0×0A
#define PCF8583_ALARM_MINS_REG     0×0B
#define PCF8583_ALARM_HOURS_REG    0×0C
#define PCF8583_ALARM_DATE_REG     0×0D
#define PCF8583_ALARM_MONTHS_REG   0×0E
#define PCF8583_ALARM_TIMER_REG    0×0F

 
//İlk NVRAM adresi yıl bilgisini tutmak için kullanılır.
#define PCF8583_YEAR_REG           0×10

 
 
//Control/Status yazmacı (register) için komutlar.
#define PCF8583_START_COUNTING     0×00
#define PCF8583_STOP_COUNTING      0×80

 
 
char const weekday_names[7][10] =
{
{”Pazar”},
{”Pazartesi”},
{”Sali”},
{”Carsamba”},
{”Persembe”},
{”Cuma”},
{”Cumartesi”}
};   
               

 
// Bu yapı kullanıcının tarih ve zaman bilgilerini tanımlar
// Değerler işaretsiz int olarak tutulur. Kullanıcı da
// PCF8583 ile haberleşmek için yazdığı programda bu aşağıdakine
// benzer bir şekilde bir yapı oluşturarak,bu sürücüdeki yazma/okuma
// fonksiyolarına değer aktarmalıdır
typedef struct
{
int8 seconds;    // 0′dan 59′a
int8 minutes;    // 0′dan 59′a
int8 hours;      // 0′dan 23′e  
int8 day;        // 1′den 31′e
int8 month;      // 1′den 12′ye
int8 year;       // 00′dan 99′a
int8 weekday;    // 0 = Pazar, 1 = Pazartesi, vs.
}date_time_t;

 
//Yazma fonksiyonu
void PCF8583_write_byte(int8 address, int8 data)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(address);
i2c_write(data);
i2c_stop();
enable_interrupts(GLOBAL);
}   

 
//Okuma fonksiyonu
int8 PCF8583_read_byte(int8 address)
{
int8 retval;

 
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(address);
i2c_start();
i2c_write(PCF8583_READ_ADDRESS);
retval = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
return(retval);
}   

 
 
void PCF8583_init(void)
{
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,
                              PCF8583_START_COUNTING);
}   

 
 
// Bu fonksiyon 8 bit ikili değeri
// 8 bit BCD değere çevirir.(Binary Coded Decimal)
// Giriş aralığı 0 ile 99 arasında olmalıdır.
int8 bin2bcd(int8 value)
{
char retval;

 
retval = 0;

 
while(1)
  {
   // Onlar basamağı, ikili değerden
   // 10 sayısını sürekli çıkararak elde edilir
   if(value >= 10)
     {
      value -= 10;
      retval += 0×10;
     }
   else // Birler basamağı kalanı ekleyerek bulunur
     {
      retval += value;
      break;
     }
   }

 
return(retval);
}

 
// Bu fonksiyon 8 bit BCD değeri
// 8 bit ikili değere çevirir.(Binary Coded Decimal)
// Giriş aralığı 0 ile 99 arasında olmalıdır.

 
char bcd2bin(char bcd_value)
{
char temp;

 
temp = bcd_value;

 
// En değerli biti sağa kaydırma
// 8 ile çarpma ile aynıdır.
temp >>= 1;

 
// Değerli bit için diğerleri izole edilir.
temp &= 0×78;

 
// Sonuç: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0×0f));

 
}

 
void PCF8583_set_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 bcd_mon;

 
// Giriş tarih/zaman bilgileri PCF8583 yazmaçlarındaki
// kayıtlara uygun olarak BCD’ye çevrilir

 
bcd_sec = bin2bcd(dt->seconds);
bcd_min = bin2bcd(dt->minutes);
bcd_hrs = bin2bcd(dt->hours);   
bcd_day = bin2bcd(dt->day) | (dt->year << 6); bcd_mon = bin2bcd(dt->month) | (dt->weekday << 5); // Tarih ve zaman yazmaçlarına kayıt yapmadan önce // saat durdurulur. PCF8583_write_byte(PCF8583_CTRL_STATUS_REG, PCF8583_STOP_COUNTING); // Tarih ve zaman yazmaçlara yazılırken i2c işlemlerinin // aksamaması için kesmeler iptal edilir. disable_interrupts(GLOBAL); i2c_start(); i2c_write(PCF8583_WRITE_ADDRESS); i2c_write(PCF8583_100S_REG); i2c_write(0×00); i2c_write(bcd_sec); i2c_write(bcd_min); i2c_write(bcd_hrs); i2c_write(bcd_day); i2c_write(bcd_mon); i2c_stop(); enable_interrupts(GLOBAL); // Yıl bilgisi NVRAM’in ilk yerine yazılır. // İkili değer olarak bırakılır. PCF8583_write_byte(PCF8583_YEAR_REG, dt->year);

 
// Şimdi PCF8583 saymaya başlatılır  
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,
                              PCF8583_START_COUNTING);
}

 
// Tarih ve zaman bilgileri PCF8583′ün yazmaçlarından okunur
void PCF8583_read_datetime(date_time_t *dt)
{
int8 year_bits;
int8 year;

 
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 bcd_mon;

 
// i2c sürecinin kesintiye uğramaması için kesmeler iptal edilir
disable_interrupts(GLOBAL);

 
// Tarih ve zaman PCF8583 yazmaçlarından alınır.
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(PCF8583_SECONDS_REG);   // Saniyeyi tutan yazmaçtan başlanır.
i2c_start();
i2c_write(PCF8583_READ_ADDRESS);

 
bcd_sec = i2c_read();     
bcd_min = i2c_read();     
bcd_hrs = i2c_read();
bcd_day = i2c_read();
bcd_mon = i2c_read(0);
i2c_stop();

 
enable_interrupts(GLOBAL);

 
// Tarih zaman değerleri BCD’den işaretsiz
// 8 bit tamsayılara çevrilir
dt->seconds = bcd2bin(bcd_sec);     
dt->minutes = bcd2bin(bcd_min);     
dt->hours   = bcd2bin(bcd_hrs & 0×3F);
dt->day     = bcd2bin(bcd_day & 0×3F);
dt->month   = bcd2bin(bcd_mon & 0×1F);
dt->weekday = bcd_mon >> 5;
year_bits   = bcd_day >> 6;   

 
// Yıl bilgisi NVRAM’dan alınır.
year = PCF8583_read_byte(PCF8583_YEAR_REG);

 
// İki bitlik yıl bilgisi entegre tarafından artırılıp
// artırılmadığı kontrol edilir. Eğer artırılmışsa
// NVRAM’deki yıl değeri bir artırılır
while(year_bits != (year & 3))
      year++;

 
dt->year = year;

 
// Yıl bilgisi hafızada güncellenir
PCF8583_write_byte(PCF8583_YEAR_REG, year);

 
}
Bu yazı CCS C Sürücü kategorisine gönderilmiş. Kalıcı bağlantıyı yer imlerinize ekleyin.