32 bit lik sayıyı eeproma yazmak ?

Başlatan KAZIMUGUR, 06 Eylül 2008, 02:16:11

KAZIMUGUR

Hi-Tide da 32 bit sayıyı eeproma nasıl yazabilirim ?

CCS de make8 kolay işti.32 biti 8 bitlik sayılar haline getirdiği gibi tersini de yapabiliyordu.

Hi-Tide kullanım kılavuzunda ve forumlarında benzer bir komut göremedim.
16 bit için ByteHi , ByteLo var ama 32 için yok. 32 için iki defamı yapmak lazım, yoksa sekizer sekizer maskeleyerekmi ?
Kolay bir yolu bilen varsa öğretirmi lütfen ?

arslan74

union 4byte_value {

long long_val;
unsigned char char_vals[4];

}


void main (void){

4byte_value.long_val = 3453634;

eeprom_write (4byte_value.char[0],yer1);
eeprom_write (4byte_value.char[1],yer2);

}


Benzer bicimde kod yazarak istediğini yapmış olursun.

Selamlar

M_B

Merhaba @arslan74 hocam;
yazdıgınız kodla alakalı bır kac sorum olacak.
Tam olarak anlayamadım. Biraz daha acıklayabilirmisiniz. Tesekkurler

sımdı hocam union yapılarını az cok bılıyorum gecenlerde calısmıtım.
union 4byte_value { 

long long_val; 
unsigned char char_vals[4]; 

}
unıonlarda her zaman bildigim icindeki en geniş elemanın saklana bilecegi kadar bellkte yer ayrılır. Burda da Long kadar ayrıldı.  
Buraya kadar sorunum yok.

unıon yapı ıcındekı  long_val =3453634; gibi bir deger verdik
sımdı bu degeri nasıl eeproma yazacagız.

eeprom_write (4byte_value.char[0],yer1); 
eeprom_write (4byte_value.char[1],yer2);
diye gosterdiniz bu kısmı anlayamadım.
Eeprom kullanımı su sekılde degılmı hocam
eeprom_write(adres,veri )

4byte_value.char[0] kısımları adres ise yer1 veri kısmı nasıl oldu o kısmı anlayamadım.  
yanı bizim 3453634 sayımızı once
    
        yer1 = long_val % 10 ; 
        yer2 = (long_val/10)%10; 
        yer3 = (long_val/100 ); 
        yer4   vb. gibi ;
parcalayım mı yazacagız. boyle yaparsak union yapıyı neden kullandık.
Hocam yoksa biraz olayı karıstırdım mı.
bu konuda acıklama yapabilirmisiniz.
Teşekkürler
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

JKramer

Ben CCS'te bu yöntemi kullanıyorum, Hi-Tec'te de kullanılabilir sanırım:
Alıntı YapHow do I write variables to EEPROM that are not a byte?

The following is an example of how to read and write a floating point number from/to EEPROM. The same concept may be used for structures, arrays or any other type.
n is an offset into the eeprom.
For example if the first float is at 0 the second
For floats you must increment it by 4.
one should be at 4 and the third at 8.

WRITE_FLOAT_EXT_EEPROM(long int n, float data) {
  int i;

  for (i = 0; i < 4; i++)
     write_ext_eeprom(i + n, *((int8*)&data + i) ) ;
}

float READ_FLOAT_EXT_EEPROM(long int n) {
  int i;
  float data;

  for (i = 0; i < 4; i++)
     *((int8*)&data + i) = read_ext_eeprom(i + n);

  return(data);
}
http://www.ccsinfo.com/faq.php?page=write_eeprom_not_byte

arslan74

Merhaba,

Öcelikle union nasıl çalışır onu anlatayım. Ama ona gecmeden önce eeprom_write() fonksiyonun parametresine incelemeden yazdım, yazlış yazmış olarabilirim. Bu durumda sadece yerlerini değiştirmeniz yeterlidir.

union (birlik) ler değişik veri türlerini birleştirmek için kullanılıyor. Şimdi biz burada ne yaptık.

long sayımızı 32 bit olarak kabul edelim. bu durumda bu sayı 4 byte uzunlukta adreste yer kaplar. onun için union içine 4 bytelik bir char dizisi ekledim.

Bu durumda ne oldu?

union bunları birleştirdi ve iki faklı türün başlangıc adreslerini aynı yaptı. Yanı long sayının başlangıc adresi ile char dizi[4] nin başlangıc adresleri aynı oldu. Bu durumda dizi[0] long un ilk ilk baytına, long un 2. baytı dizinin [1] indisli elemanına, long un 3. baytı dizinin [2] indisli elemanına, long un 4. baytı dizinin [3] indisli elemanı denk geliyor.

eeprom yazmak için bu değerleri byte olarak yazmamız gerekdiği için char dizini kullanarak yaziyoruz. aynı şeklide eepromda okuma yaptığımızda da char dizisine yerleştiriyoruz. bu yerleştirme bittikten sonra long değerinizi elde ederiz.

Aşağıda şekilde anlatılmış.



Ayrıca aşağıdaki linki inceleyin daha ayrıntılı anlatmış. incelemenizi tavsi ederim.

http://www.cplusplus.com/doc/tutorial/other_data_types.html

Selamlar

mihri

////////////// 4 Byte Veri Yazma //////////////

void ee_yaz(*ptr,char addr)
{
	eeprom_write (*ptr,addr);
	addr++;
	ptr++; 
	eeprom_write (*ptr,addr);
	addr++;
	ptr++;
	eeprom_write (*ptr,addr);
	addr++;
	ptr++;
	eeprom_write (*ptr,addr);

	return;
}

//////////////// 4 Byte Veri Okuma /////////////

float ee_oku(char addr)
{
	float 4_byte;
	char *ptr;
	
	ptr = &4_byte;
	
	*ptr = eeprom_read(addr);
	ptr++;
	addr++;
	*ptr = eeprom_read(addr);
	ptr++;
	addr++;
	*ptr = eeprom_read(addr);
	ptr++;
	addr++;
	*ptr = eeprom_read(addr);

	return 4_byte;
}


Kodu denemedim ama büyük ihtimalle çalışacaktır.

Kolay gelsin. 8)
"Eppur si muove!"

cemilkendir

peki arkadaşlar negatif bir float değişkeni eproma nasıl kayıt ederiz
benim yaptığım yöntem şu (CCS Cile yazıyorum)

void eprom_yaz(float veri,int adres){
   int16 veri2;
   int yaz1,yaz2;
   if(veri<0)
      {
      write_eeprom(adres,1);
      veri=veri*(-1);
      }
   else
      write_eeprom(adres,0);
   veri=veri*10;
   veri2=(int16)veri;
   yaz1=veri2/100;
   yaz2=veri2%100;
   write_eeprom(adres+1,yaz1);
   write_eeprom(adres+2,yaz2);
  
}
   
float eprom_oku(int adres){
    float sonuc;
    sonuc=(read_eeprom(adres+1)*10.0)+(read_eeprom(adres+2)/10.0);
    if(read_eeprom(adres)==1)
      sonuc=sonuc*(-1);
    return sonuc;
   }


benim kullandığım ondalıklı sayılar 12.34 gibi virgülden sonra iki haneli
böyle bir sayıyı yazdırmak için 3bytelık yer kullanıyorum epromda
1.byte sayının negatif yada pozitif olduğunu tutuyor.
2.byte sayının tam kısmını
3.byte ise ondalıklı kısmını tutuyor

bu yöntem dışında bana başka bir yöntem önerebilirmisiniz yada sizin kullandığınız bir kod varmı

arslan74

Madem işi pointer ile yapmak istiyorsanız size pointer versiyonunun vereyim.


eeprom_write(adres,veri )


şekilde ise o zaman eeprom'un 1. adresinden 4 byte uzunluğunda long veya float bir sayıyı yazmaya başlayalım.

eeprom_write(1,*((unsigned char*)&long_sayi) );

eeprom_write(2,*(((unsigned char*)&long_sayi)+1) );

eeprom_write(3,*(((unsigned char*)&long_sayi)+2) );

eeprom_write(4,*(((unsigned char*)&long_sayi)+3) );


Bu şekilde yazabilirsiniz. Ama okunabilirliği ve anlaşılması cok düşük olduğu için pointerlere hiç girmeden halledecek bir yöntem söyledim.

Secim size kalmış.

Selamlar.

Tagli

Bu başlıkta benzer bir konu üzerinde kafa patlatmıştık. Bir inceleyin belki faydası olur.

@cemilkendir, uyguladığın yöntem her ne kadar anlaşılması ve programlanması kolay da olsa verimlilikten uzak. Özellikle işaret için sadece 1 bit gerekirken senin bu veriyi 8 bit kullanarak saklaman 1 byte'ın israfı demek bence.
Gökçe Tağlıoğlu

cemilkendir

Alıntı yapılan: "Tagli"Bu başlıkta benzer bir konu üzerinde kafa patlatmıştık. Bir inceleyin belki faydası olur.

@cemilkendir, uyguladığın yöntem her ne kadar anlaşılması ve programlanması kolay da olsa verimlilikten uzak. Özellikle işaret için sadece 1 bit gerekirken senin bu veriyi 8 bit kullanarak saklaman 1 byte'ın israfı demek bence.

bana da öyle geldi zaten onun için bir fikir alayım dedim

derleyicinin sürücü dosyalarında şöyle bir şey buldum bunu kullanacağım

void write_float_eeprom(int8 address, float data)
{
   int8 i;

   for(i = 0; i < 4; ++i)
   {
     write_eeprom(address + i, *((int8 *)(&data) + i));
   }
}


float read_float_eeprom(int8 address)
{
   int8 i;
   float data;

   for(i = 0; i < 4; ++i)
   {
     *((int8 *)(&data) + i) = read_eeprom(address + i);
   }

   return data;
}