LPC2478 EEPROM Yazma

Başlatan ugurer, 02 Kasım 2017, 16:51:32

ugurer

Merhabalar, LPC2478 ile AT24C256C eeprom'u kullanmaya çalışıyorum. Devre normalde kullandığımız bir devre o yüzden devreyle alakalı bir hata olasılığı yok. Eeprom'dan veri okuyabiliyorum 0xFF olarak fakat ne yaptıysam veri yazmayı beceremedim. Nerede hata yaptığımı bulamadım bir türlü.
/****** Yazma Kismi********************/	 
		 putchar0('-');
		 putchar0('A');
		 putchar0('-'); 
		 I2C_start();
		 I2C_write(0xA0);
         	 I2C_write(ugur_adres>>8);
		 I2C_write(ugur_adres&0xFF);
		 I2C_write(ugurgit);
		 for(say=0; say<10000; say++){high2(SDA);high2(SCL);I2C_delay();low2(SCL);}
		 I2C_stop();
		 for(say=0; say<10000; say++);
/****** Yazma Kismi*******************/	 
/****** Okuma Kismi*******************/	 
		 putchar0('-');
                 putchar0('B'); 
                 putchar0('-'); 
		 I2C_start(); 
		 I2C_write(0xA0);
		 I2C_write(ugur_adres>>8);
		 I2C_write(ugur_adres&0xFF);
		 I2C_start();			/* Start i2c bus */     
	         I2C_write(0xA0+1);/* Connect to EEPROM for Read */
	         ugurgel = I2C_read();		/* Receive data */
		 I2C_noack();
	         I2C_stop();				/* Stop i2c bus */

/************************************/
     for(say=0; say<500000; say++);
		 putchar0(ugurgel);
		 putchar0('\n');
		 reset_wdt();

ugurer

Osiloskop şu an elimde olmadığı için pin durumuna göre ekrana 0 1 yazdırdım o kısım da doğru yani tam olması gerektiği gibi. Şu bekleme kısmıyla alakalı bir durum olduğunu düşünüyorum fakat çözemedim.

ugurer

Normal Eeprom rutinimde sıkıntı var anladığım kadarıyla o konu da yardımlarınızı bekliyorum.

JOKERAS

I2C Bit fonksiyonları nerede?


Bit Fonksiyonlarında SDA ve SCL'nin Fonksiyonları çağrıldığında ki giriş çıkış durumları
önemli.
Bit Fonksiyon çıkışlarında SDA her zaman High-İdle, SCL her zaman Low olmalı.
SCL sadece Stop Gönderildiğinde High olmalı,bu SCL'nin yeni başlangıcı için High.


ugurer

#define I2C_DELAY 0xF	/* For delay i2c bus */

void I2C_delay(void)
{
	unsigned char index1;

	for(index1=0; index1<I2C_DELAY; index1++); 
}

#ifdef Board_Type_2478_port_1_3
void I2C_clock(void)
{
	I2C_delay();

	high2(SCL);    //      SCL = 1;		/* Start clock */

	I2C_delay();    

	low2(SCL);    //  SCL = 0;		/* Clear SCL */

	//I2C_delay();
}

void I2C_start(void)
{
	low2(SCL);    //  SCL = 0;		/* Clear SCL */

	high2(SDA);    //  SDA = 1;        /* Set SDA */
	high2(SCL);    //  SCL = 1;		/* Set SCL */

	I2C_delay(); 

	low2(SDA);    //  SDA = 0;        /* Clear SDA */

	I2C_delay(); 

	low2(SCL);    //  SCL = 0;        /* Clear SCL */
}

void I2C_stop(void)
{
	//if(SCL)	
	low2 (SCL);    //  SCL = 0;			/* Clear SCL */

	low2(SDA);    //  SDA = 0;			/* Clear SDA */
	I2C_delay();

	high2(SCL);    //  SCL = 1;			/* Set SCL */

	I2C_delay();

	high2(SDA);    //  SDA = 1;			/* Set SDA */
	

}

unsigned char I2C_write(unsigned char dat)
{
	tByte data_bit = 0;		
	unsigned char i;
	tByte  suan=0;
	for(i=0;i<8;i++)				/* For loop 8 time(send data 1 byte) */
	{
		data_bit = dat & 0x80;		/* Filter MSB bit keep to data_bit */
		if(data_bit)
		{	high2(SDA);}// putchar0('1');}
		else
		{low2(SDA); }//putchar0('0');}
		//SDA = data_bit;				/* Send data_bit to SDA */

		I2C_clock();      			/* Call for send data to i2c bus */
			 
		if(i != 7)
		dat = dat<<1;  
	}
	

	high2(SDA);    //  SDA = 1;			/* Set SDA */

	FIO2DIR &= ~SDA;	   // Set SDA input

	high2(SCL);    //  SCL = 1;			/* Set SCL */

	I2C_delay();

	
	//data_bit = SDA;   	/* Check acknowledge */
	data_bit = FIO2PIN & SDA ;

	low2(SCL);    //  SCL = 0;

	FIO2DIR |= SDA ;    //Set SDA output
	return data_bit;	/* If send_bit = 0 i2c is valid */		 	
}

unsigned char I2C_read(void)
{
	unsigned int  rd_bit;	
	unsigned char i, dat;

	dat = 0x00;	

	FIO2DIR &= ~SDA;	   // Set SDA input

	for(i=0;i<8;i++)		/* For loop read data 1 byte */
	{
		//I2C_delay();

		high2(SCL);    //  SCL = 1;			/* Set SCL */

		I2C_delay(); 

		rd_bit = FIO2PIN & SDA ;
		//rd_bit = SDA;		/* Keep for check acknowledge	*/
		
		if(rd_bit)
			dat = dat | 0x01;// putchar0('1');}
		//else putchar0('0');
		if(i != 7)
			dat = dat<<1;		
		//dat = dat | rd_bit;	/* Keep bit data in dat */

		low2(SCL);    //  SCL = 0;			/* Clear SCL */
	}

	FIO2DIR |= SDA ;    //Set SDA output

	return dat;
}

void I2C_ack(void)
{
	low2(SDA);    //  SDA = 0;		/* Clear SDA */

	I2C_delay();    

	I2C_clock();	/* Call for send data to i2c bus */

	high2(SDA);    //  SDA = 1;		/* Set SDA */
}

void I2C_noack(void)
{
	high2(SDA);    //  SDA = 1;		/* Set SDA */

	I2C_delay();

	I2C_clock();	/* Call for send data to i2c bus */

	high2(SCL);    //  SCL = 1;		/* Set SCL */
}


Register kısmını da paylaşabilirim isterseniz fakat biraz karışık bir alanda. Okuma yaparken sorunsuz kullanıyorum fakat yazma kısmını halledemedim bir türlü.

JOKERAS

         for(i=0;i<8;i++) {
	
	   if((dat & 0x80) == 0) {
               low2(SDA);
           } 
           high2(SDA);     //Sda her halukarda İdle.
           I2C_clock();     //ScL fonskiyondan çıktığında Low. 			
	   dat = dat<<1;  
       }


Write Fonksiyonun for kısmını şu şekilde denermisiniz?

ugurer

Maalesef bir değişiklik olmadı. EEprom okuma kısmı hala çalışıyor 'FF' okuyorum fakat yazma kısmı çalışmadı yine.

JOKERAS

ugurer, okuma yaptığınızdan eminmisiniz?
Daha sade bir şekilde Bit fonksiyonlarını sonra da Byte fonksiyonlarını
yazın.


Bu kodu sizmi yazdınız yoksa bir yerdenmi aldınız?


ugurer

#define low2(x) FIO2CLR |= x	//; //FIO0CLR |= x ;
#define high2(x) FIO2SET |= x //; //FIO0SET |= x	;
	#define SCL      0x00008000        // P0.15
	#define SDA      0x00040000        // P0.18
////////********Tanımlamalar*///////////////////
void I2C_delay(void)// Delay Fonksiyonu
{
	unsigned char index1;

	for(index1=0; index1<I2C_DELAY; index1++); 
}
void I2C_start(void)//Start Fonksiyonu
{
	low2(SCL);    //  SCL = 0;		/* Clear SCL */

	high2(SDA);    //  SDA = 1;        /* Set SDA */
	high2(SCL);    //  SCL = 1;		/* Set SCL */

	I2C_delay(); 

	low2(SDA);    //  SDA = 0;        /* Clear SDA */

	I2C_delay(); 

	low2(SCL);    //  SCL = 0;        /* Clear SCL */
}
void I2C_stop(void)// Stop Fonksiyonu
{
	//if(SCL)	
	low2 (SCL);    //  SCL = 0;			/* Clear SCL */

	low2(SDA);    //  SDA = 0;			/* Clear SDA */
	I2C_delay();

	high2(SCL);    //  SCL = 1;			/* Set SCL */

	I2C_delay();

	high2(SDA);    //  SDA = 1;			/* Set SDA */
	

}
unsigned char I2C_write(unsigned char dat)// Yazma Kısmı
{
	tByte data_bit = 0;		
	unsigned char i;
	tByte  suan=0;
	for(i=0;i<8;i++)				/* For loop 8 time(send data 1 byte) */
	{
		data_bit = dat & 0x80;		/* Filter MSB bit keep to data_bit */
		if(data_bit)
		{	high2(SDA);}// putchar0('1');}
		else
		{low2(SDA); }//putchar0('0');}
		//SDA = data_bit;				/* Send data_bit to SDA */

		I2C_clock();      			/* Call for send data to i2c bus */
			 
		if(i != 7)
		dat = dat<<1;  
	}
	

	high2(SDA);    //  SDA = 1;			/* Set SDA */

	FIO2DIR &= ~SDA;	   // Set SDA input

	high2(SCL);    //  SCL = 1;			/* Set SCL */

	I2C_delay();

	
	//data_bit = SDA;   	/* Check acknowledge */
	data_bit = FIO2PIN & SDA ;

	low2(SCL);    //  SCL = 0;

	FIO2DIR |= SDA ;    //Set SDA output
	return data_bit;	/* If send_bit = 0 i2c is valid */		 	
}
unsigned char I2C_read(void)// Okuma Kısmı
{
	unsigned int  rd_bit;	
	unsigned char i, dat;

	dat = 0x00;	

	FIO2DIR &= ~SDA;	   // Set SDA input

	for(i=0;i<8;i++)		/* For loop read data 1 byte */
	{
		//I2C_delay();

		high2(SCL);    //  SCL = 1;			/* Set SCL */

		I2C_delay(); 

		rd_bit = FIO2PIN & SDA ;
		//rd_bit = SDA;		/* Keep for check acknowledge	*/
		
		if(rd_bit)
			dat = dat | 0x01;// putchar0('1');}
		//else putchar0('0');
		if(i != 7)
			dat = dat<<1;		
		//dat = dat | rd_bit;	/* Keep bit data in dat */

		low2(SCL);    //  SCL = 0;			/* Clear SCL */
	}

	FIO2DIR |= SDA ;    //Set SDA output

	return dat;
}


Okuma rutinim ise
while(1)
{
/****** Yazma Kismi********************/	 
		 putchar0('-');
		 putchar0('A');
		 putchar0('-'); 
		 I2C_start();
		 I2C_write(0xA0);
	   I2C_write(ugur_adres>>8);
		 I2C_write(ugur_adres&0xFF);
		 I2C_write(ugurgit);
		 I2C_stop();
		 for(say=0; say<bekle; say++) high2(SDA);
		 putchar0(ugurgit);
/****** Okuma Kismi*******************/	 
		 putchar0('-');
     putchar0('B'); 
     putchar0('-'); 
		 I2C_start(); 
		 I2C_write(0xA0);
		 I2C_write(ugur_adres>>8);
		 I2C_write(ugur_adres&0xFF);
		 I2C_start();			/* Start i2c bus */     
	   I2C_write(0xA0+1);/* Connect to EEPROM for Read */
	   ugurgel = I2C_read();		/* Receive data */
		 I2C_noack();
	   I2C_stop();				/* Stop i2c bus */

/************************************/
     for(say=0; say<bekle; say++);
		 putchar0(ugurgel);
		 putchar0('\n');
		 reset_wdt();
		 		 
		}

ugurer

İnternetten bulduğum başka bir LPC için olan kodu dönüştürdüm kendimce. Ama pin durumlarını okuyorum düzgün bir şekilde çalışıyor. Okuduğumu da şuradan düşünüyorum read fonksiyonunu kapatıp ekrana yazdırdığımda ekrana boş değer basıyor fakat read'le birlikte yazdırınca 0xFF değerini görüyorum.

SDA pininin durumları da şu şekilde

/******** Yazarken SDA Pİni**********/
    0xA0      Adres_H   Adres_L     Yazdırdığım data
10100000/00000000/00011100/00001001
/********Okuma Kısmında SDA********/
   0xA0      Adres_H    Adres_L     Okuma isteği
10100000/00000000/00011100/101010001

0xA0 Eeprom adresi, Okuma isteği kısmı da 0xA1 datasheet'ten okuduğum değer.

ugurer

@JOKERAS hocam var mı bir tahmininiz ya da çözüm öneriniz ?

JOKERAS

ugurer,


Sda high, Hi-z olacak yani İdle.
Sda Low,  çıkış 0 olacak.


Start fonksiyonunda SCL High olarak başlamalı.



char Start (void) {


        SCLHigh();        //SCL High.   
        SDALow();        //SDA Low START.
   
        SCLLow();         //SCL Low olduğu anda Start olmuş demektir.Start onay Clock'u
        SDAHigh();       //SDA Hi-z (İdle).SDA hattındaki R-Pullup SDA hattının Lojik 1 olmasını sağlayacak.
                               //Yani SDA hattını siz 1 yapmayacaksınız.

}


I2C protokolunde fonksiyon giriş çıkışlarında SDA ve SCL hatlarının durumları ve sıraları önemli.
Linkte Timing'i var.

https://www.i2c-bus.org/repeated-start-condition/


   




ugurer

Hocam Hi-Z dediğiniz olayı tam kavrayamadım Set ve Clear işlemleri var görebildiğim kadarıyla datahsheet'te. Register fonksiyonlarını baştan yazmayı deneyeceğim belki orada bir hatam vardır.

JOKERAS

Hi-z Yüksek empedans.
Portların 3 konumu vardır.Theree State Buffer.
İşlemcilerdeki "TRISA" "TRISB" "TRISC" vs buradan gelir.


1.Durum PORT giriş.
2.Durum PORT çıkış.
3.Durum Hi-z-Yüksek Empedans.Buna Pullup Takarsanız İdle olur.


Mesela bir Portu Hi-z  olarak kurup bir direnç ile de Pullup yapıp bu portu okuduğumuzda
Lojik 1 görürüz.
Bu önemli neden?Master cihaz Slave cihaza "0" yollarken Sda hattını kendisi zorla 0 yapacak.
"1" yaparken ise Sda hattını Hi-z yapacak.Sda Hattındaki R-Pullup bu hattı idle'a yani Lojik 1'e çekecek.
Bunun sebebi I2C Slave cihazın içsel yapısıyla,hızıyla alakalı.
Aynı zamanda Slave cihazı,Ack cevabı vermek için Sda hattını Lojik 0'a çekerek Cevap verecek
Yukarıdaki 1. ve 2. durumda bunu nasıl yapabilecek?


3. durum yani Hi-z İdle olmalıki hattı 0'a çekip Ack cevabı verebilsin.



I2C Start Timingine bakarsanız bir frame var.Frame'in başlangıç ve bitişine bakın.
Frame başlarken nasıl,biterken nasıl?