DS1307 nasıl çalışır

Başlatan 3ddark, 12 Ekim 2008, 23:00:03

3ddark

Ben bu DS1307 için kendi kütüpane kodumu hazırlamak istiyorum ama biraz sorunum var ben bu DS1307 nasıl çalışır nasıl haberleşir tam olarak çözemedim yardımlarınızı bekliyorum alttaki resimde ve datasheetinde gösterilenlere (resimler datasheeten) göre önce SDA vs SCL ayaklarını START için hazırlanacak daha sonra yazma veya okuma moduna göre SLAVE ADRESS bilgisi gönderilecek yazmak için 0xd0 okumak için 0xd1 olacak şekilde MSB bilgisi ilk önce olmak üzere seri olarak gönderecegiz daha sonra ACK (acknowledfe) bu nedir tam olarak bilgmiyorum onay kodu gibi birşey ama anlamadım buraya kadar tamam. Bunda sonra gelen 1 bytelık her veri nedir.
Örnek ben saniye bilgisi okumak istiyorum nasıl okuyacağım saniye DS1307 00H adresinde kayıtlı ben bu bilgiyi hangi yolu izleyerek okurum.
Benim sorunum tarih okuma  veya yazma bilgi akışı hangi sıraya göre nasıl yapılıyor.

Yapılacak çok şey var

f_machine

ack,slave den gelen onay oluyor burda.
ds1307 den bilgi okurken ise,hatırladığım kadarıyla,adres 00h tan başlıyor,sonra okuduğun her byte
için ds1307 nin program counter ı 1 artıyor,bu şekilde saniye,saat falan filan hepsini arka arkaya okuyorsun...

Logan

DS 1307 protokolü, bildiğimiz i2c protokolüdür. Sadece adres değerleri farklıdır.
İmza.

3ddark

f_machine ve Logan  benim problemim okuma işlemi ve yazma işlemi nasıl bir sıra izliyor yani okuma yapmak istedigim zaman önce hangi kodu gönderecegim ilk yazdığımda örnek olarak yazmıştım şimdi ben saniye ve dakika bilgisini okumak istesem.  Önce

START - SLAVE READ ADRESS (0xd1) - ACK - 
bundan sonra saniye ve dakika nasıl okurum 00 adresine ve 01 adresine saniye ve dakika bilgisini almak için nasıl ulaşırım. o arada yazma işlemimi yapacağım problem burada.
Yapılacak çok şey var

XX_CİHAN_XX

Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

Logan

@3ddark, aşağıdaki linkte I2C protokolü detaylı bir biçimde anlatılmıştır. eprom ile DS107 arasındaki tek fark "KONTROL ADRESLERİ" nin farklı olmasıdır. Eğer ds1307'nin data sheetinin 9. sayfasını inceleyecek olursan, saat-dakika- gün gibi bilgilerin, 0. registerden başlamak suretiyle arka arkaya dizilmiş olduğunu göreceksin. Bakınız şekil 1.a ;



Senin de görmüş olduğun gibi saniye-dakika-gün-haftanın günü-ayın günü-ay ve yıl olmak üzere datalar sıralanmış. 07h adresi ise kontrol registeridir. Entegrenin 7. bacağını, bu değişken ile flip-flop çıkışı yapabilir, ayrca frekansını ayarlayabilirsin. Kolay gelsin.

DS1307 açıklama
İmza.

3ddark

Teşekkür ederim yardımlarınız için bende bi yandan araştırırken ziya hocanın bi makalesini gördüm antrak dan oradaki epromlar ile ilgili olan epey yardımcı oldu bana sadece eprom ile farkı adres ise sorun değil okunacak olan adres saniye icin 00 seçilecek bundan sonrası basit teşekkürler kolay gelsin ben şimdiden zaman buldukça yazayım.
Yapılacak çok şey var

sigmoid

kullandığım kodu veriyorum.

i2c.h dosyası
/**********************************************************
*  Yazar 	: Abdullah Özdemir
*  Web 		: http://arkaoda.zerreelektronik.com
*  İlk		: Eylül 2008
*  Düzenleme: Yok 
*  Versiyon : 0.1
*  Açıklama :  i2c master mode
***********************************************************/
#ifndef	XTAL_FREQ
	#define	XTAL_FREQ	20MHZ
	#define	MHZ	*1000UL
	#define	KHZ	*1			
#endif

#define I2CHIZ	400KHZ	//istenilen  hız (100KHZ,1MHZ ) buraya yazılacak. 

//#define slewrate  //100khz ve 1mhz için yazılmalı, 400khz high speed için bu parametre silinmeli

#define I2CHIZREG ((XTAL_FREQ/I2CHIZ/4)-1)

#define ack	0	//acknowledge
#define noack	1	//not acknowledge

void i2c_kur(void);
void i2c_baslat(void);
void i2c_durdur(void);
void i2c_yenidenbaslat(void);
char i2c_yaz(char veri);
char i2c_oku(char onay);


i2c.c dosyası
/**********************************************************
*  Yazar 	: Abdullah Özdemir
*  Web 		: http://arkaoda.zerreelektronik.com
*  İlk		: Eylül 2008
*  Düzenleme: Yok 
*  Versiyon : 0.1
*  Açıklama : i2c master mode
*  100KHz için 10K, 400Khz için 2K pull up direnci kullanılmalıdır.
***********************************************************/
#include <pic.h>
#include "i2c.h"


//Başlangıç olarak i2c modulunü master olarak ayarlar.
void i2c_kur(void)
{
 #ifdef slewrate
	SSPSTAT=0x80;
 #else
 	SSPSTAT=0x00;	
 #endif
	SSPADD=I2CHIZREG;
	SSPCON=0x28;
	SSPCON2=0x00;	
	TRISC3=1;
	TRISC4=1;
}

//start sinyalini gönderir.
void i2c_baslat(void)
{
	SSPIF=0;
	SEN=1;	//start bitini gönder.
	while(!SSPIF); //start bitinin gönderilmesinin bitmesini bekle
}

//restart sinyalini gönderir
void i2c_yenidenbaslat(void)
{
	SSPIF=0;
	RSEN=1;	//restart bitini gönder.
	while(!SSPIF);
}

//stop sinyalini gönderir.
void i2c_durdur(void)
{
	SSPIF=0;
	PEN=1;	//stop bitini gönder.
	while(!SSPIF);
}


//1 byte veriyi gönderir, ack sinyalini okur
char i2c_yaz(char veri)				
{
	SSPIF=0;
	SSPBUF=veri;
	while(!SSPIF);
	return ACKSTAT;	//0 dönerse ack alınmış demektir.
}

//1 byte veri okur ack sinyali gönderir.
char i2c_oku(char onay)	
{
	char temp;
	SSPIF=0;
	RCEN=1;
	while(!SSPIF);
	temp= SSPBUF;
	ACKDT=onay;  //0 = ack, 1=noack
	SSPIF=0;
	ACKEN=1;
	while(!SSPIF);
	return temp;
}

sigmoid

ds1307.h dosyası
/**********************************************************
*  Yazar 	: Abdullah Özdemir
*  Web 		: http://arkaoda.zerreelektronik.com
*  İlk		: Eylül 2008
*  Düzenleme: Yok 
*  Versiyon : 0.1
*  Açıklama :  Maxim DS1307 RTC driverı
***********************************************************/

//saat modu
#define saatmodu24	0
#define saatmodu12	1

#define ogledensonra 	1
#define ogledenonce 	0


char saat_ayalarlanmismi(void);
void saat_ayarla(void);
void saat_oku(void);
void saat_ram_yaz(char adres,char veri);
char saat_ram_oku(char adres);


ds1307.c dosyası
/**********************************************************
*  Yazar 	: Abdullah Özdemir
*  Web 		: http://arkaoda.zerreelektronik.com
*  İlk		: Eylül 2008
*  Düzenleme: 
*  Versiyon : 0.11
*  Açıklama :  Maxim DS1307 RTC driverı
* SQW çıkışından kare dalga almak için bu pin pull-up yapılmalıdır.
* Vbat (yedek pil) kullanılmayacaksa 100K ile pulldown yapılmalı. yoksa saat geri kalıyor.
***********************************************************/
#include <pic.h>
#include "i2c.h"
#include "ds1307.h"

//i2c hızı max. 100KHz olmalıdır.

//aşağıdaki değişkenler yanında 10 olan değişkenler onlar basamağını ifade etmektedir.
//her değişken 0 ile 9 arasında rakam tutar. saat_ayarla ve saat_oku fonksiyonları bu değişkenleri günceller.
//extern parametresi ile main içine kopyalanmalıdır.
char saniye10,saniye,dakika10,dakika,saat10,saat;
char ay10,ay,gun10,gun,yil10,yil,haftaningunu;	//pazar için=1, pazartesi=2...
char saatmodu;	//1=12 saatmodunda, 0 için= 24 saat modu.
char pm;  //0 ise am, 1 ise pm dir.

//saatin ayarları yapılmış ise 0, yapılmamışsa 1 döner.
char saat_ayalarlanmismi(void)
{
	char temp;
	i2c_baslat();
	i2c_yaz(0xd0);	//ds1307 adresi. yazma modunda.
	i2c_yaz(0x00);	//word adres.
	i2c_yenidenbaslat();
	i2c_yaz(0xd1);	//ds1307 adresi. okuma modu.
	temp=i2c_oku(noack);
	i2c_durdur();
	if (temp & 0x80)
	  return 1;	// ayarlanması gerekli
	else
 	  return 0;	//saat ayarlanmış.
}	

//registerlerı günceller
void saat_ayarla(void)
{
	char temp;
	i2c_baslat();
	i2c_yaz(0xd0);
	i2c_yaz(0x00);
	//saniyeyi yaz ve osilatörü aktifleştir.
	i2c_yaz(0x00);
	//dakikayı yaz.
	temp=(dakika10 <<4) |dakika;
	i2c_yaz(temp);
	//saati yaz.
	if(saatmodu)	//12 saat modunda
	{
		if(pm)	//öğleden sonra mı
			temp=0x60 | (saat10<<4) | saat;
		else
			temp=0x40 | (saat10<<4) | saat;
	}
	else
		temp=(saat10<<4) | saat;
	i2c_yaz(temp);
	//haftanın gununu yaz
	i2c_yaz(haftaningunu);
	//gunu yaz.
	temp=(gun10<<4) | gun;
	i2c_yaz(temp);
	//ay ı yaz.
	temp=(ay10<<4) |ay;
	i2c_yaz(temp);
	//yılı yaz.
	temp=(yil10<<4)|yil;
	i2c_yaz(temp);
	//control wordu yaz. 1hzlik kare dalga.
	i2c_yaz(0x10);
	i2c_durdur();	
}	


//tüm registerları okur.
void saat_oku(void)
{
	char temp;
	i2c_baslat();
	i2c_yaz(0xd0);
	i2c_yaz(0x00);
	i2c_yenidenbaslat();
	i2c_yaz(0xd1);
	//saniyeyi oku
	temp=i2c_oku(ack);
	saniye=0x0f & temp;
	saniye10=(temp>>4) & 0x7;
	//dakikayı oku.
	temp=i2c_oku(ack);
	dakika= temp & 0x0f;
	dakika10=temp >>4;
	//saati oku.
	temp=i2c_oku(ack);
	saat=temp & 0x0f;	
	if(temp &0x40)//12 saatmodunda mı
	{
		saatmodu=1;
		saat10=(temp>>4) & 0x01;
		pm=(temp>>5) &0x01;		
	}
	else
	{
		saatmodu=0;
		saat10=(temp>>4) & 0x03;
	}		
	//haftanın gününü oku
	haftaningunu=i2c_oku(ack);
	//gunu oku
	temp=i2c_oku(ack);
	gun=temp &0x0f;
	gun10=temp>>4;
	//ay ı oku.
	temp=i2c_oku(ack);
	ay=temp & 0x0f;
	ay10=temp>>4;
	//yılı oku.
	temp=i2c_oku(noack);
	yil=temp & 0x0f;
	yil10=temp>>4;
	i2c_durdur();	
}

//56 bytelık ramınden okuma yazma için.	
//adres 0 ile 55 arasında olmalıdır.
void saat_ram_yaz(char adres,char veri)
{
	i2c_baslat();
	i2c_yaz(0xd0);
	i2c_yaz(adres+0x08);
	i2c_yaz(veri);
	i2c_durdur();
}

char saat_ram_oku(char adres)
{
	char temp;
	i2c_baslat();
	i2c_yaz(0xd0);
	i2c_yaz(adres+0x08);
	i2c_yenidenbaslat();
	i2c_yaz(0xd1);
	temp=i2c_oku(noack);
	i2c_durdur();
	return temp;
}		

/*
0.11 saat_oku() içinde saat okurken karşılaşılan hata düzeltildi.
    pm,saat10 değeri okuma ve yazma hatası düzeltildi.
*/

sigmoid

Kullanımı:

ilk olarak main.c dosyasında
extern char saniye10,saniye,dakika10,dakika,saat10,saat; 
extern char ay10,ay,gun10,gun,yil10,yil,haftaningunu;   //pazar için=1, pazartesi=2... 
extern char saatmodu;   //1=12 saatmodunda, 0 için= 24 saat modu. 
extern char pm;  //0 ise am, 1 ise pm dir.


şeklinde değişkenleri tanımlayalım.
ds1307i 3v luk cr2032 pili ile besleyebilirsin böylece saat devrede elektrik olmasa bil çalışır.

Programında saat_ayalarlanmismi() fonksiyonu ile ds1307 nin saatinin önceden ayarlanıp ayarlanmadığını öğrenirsin. Bu fonksiyon çalıştırıldığında eğer 1 dönüyorsa saat ayarlanmamıştır. Saat değerlerini yazman gerekir.

saati ayarlamak için saniye, saniye10 ,dakika, dakika10, saat,saat10 vb gibi tüm değişkenlere değerleri girip saat_ayarla() fonksiyonunu çalıştır.
Saati okumak için saat_oku() fonksiyonunu çalıştırdığında saat10,saat,dakika10,dakika vb tüm değişkenler ds1307 den okunup güncellenir.

saat10 gibi yanında 10 yazan değişken onlar basamağını temsil eder. Örneğin 12: 54 yazmak için
saat10=1;
saat=2;
dakika10=5;
dakika=4;
yazman yeterli.

kolay gelsin.

3ddark

# abdullaho gönderdiğin dosya için teşekkür ederim ama saat_oku fonksiyonunda
i2c_baslat_k();
i2c_yaz_k(0xd0); bu şekilde devam eden _k ile biten fonksiyon çağırma işlemleri mevcut ve senin gönderdiğin dosyalar içerisinde

#include "i2c_k.h"
bu dosya yok eksik göndermişsin veya gözden kaçırmışsın bu dosya yok !
Yapılacak çok şey var

sigmoid

kodlarda gerekli düzeltmeleri yaptım.