Struct değişkenini long değişkene aktarma

Başlatan selimkoc, 01 Ağustos 2017, 10:22:29

selimkoc

Merhaba forum üyeleri,

aşağıdaki yapıda long tipindeki değişkene yapıyı aktarmak istiyorum. Ama başarısız oldum. Amacım tarih ve saat bilgisini daha az EEpromda saklamak. Normal saklamak istersem 6 byte alan gerekiyor. Bu şekilde 4 byte sığdırabiliyorum. Long temp değişkenini 4 byte bölüp eepromda saklamayı düşünüyorum.

  long temp=0; 
  
  struct tarihSaat {
    byte yil:5;
    byte ay:4;
    byte gun:5;
    byte saat:5;  
    byte dakika:6;
    byte islem:2;    
  };

  tarihSaat zaman={17,7,24,12,50,1};



baran123

typedef union
{
struct tarihSaat {
    byte yil:5;
    byte ay:4;
    byte gun:5;
    byte saat:5;  
    byte dakika:6;
    byte islem:2;    
  }

struct {
long temp;
}
}Datastruct_t;

Datastruct_t myStruct;

mystruct.gun = 3;
...
...

long tempData = myStruct.temp;

selimkoc

typedef union
{
struct tarihSaat {
    byte yil:5;
    byte ay:4;
    byte gun:5;
    byte saat:5;  
    byte dakika:6;
    byte islem:2;    
  };

struct {
long temp;
};
}Datastruct_t;

Datastruct_t myStruct;
myStruct.yil=17;
myStruct.ay=7;
myStruct.gun=24;
myStruct.saat=12;
myStruct.dakika=50;
myStruct.islem=1;
long tempData = myStruct.temp;


"myStruct" does not name a type  hatası alıyorum.

Klein

Değişkenler arası aktarımın çok yolu var. Fakat 6 byte  uzunluktaki bir yapıyıı 4 byte uzunluğunda bir değişkene aktarmanın bir yolu olduğunu zannetmiyorum. Ancak 4 baytlık kısmını aktarabilirsiniz.
Fakat sisteminiz 32 bit ise Long değişkeniniz 8 byte olacaktır. O zaman aktarabilirsiniz.
En basit yolu

temp = *(long *)&tarihsaat;

şeklinde olur. Fakat burada şöyle bir sorun olur. long uzunluğu 8 byte ise , tarihsaat yapısının sonrasındaki 2 baytlık kısmı da alır.

6 baytlık bir yapıyı 4 bayta nasıl sığdırdığınızı biraz daha açarsanız, belki daha uygun yollar bulabiliriz.

M_B

typedef union{
long temp;
    struct 
      {
          char yil:5;
          char ay:4;
          char gun:5;
          char saat:5;
          char dakika:6;
          char islem:2;
       };
}Datastruct_t;

 Datastruct_t  myStruct;
 long tempData;


   myStruct.yil=17;
   myStruct.ay=7;
   myStruct.gun=24;
   myStruct.saat=12;
   myStruct.dakika=50;
   myStruct.islem=1;

tempData = myStruct.temp;

Hocam işinizi gorur mu ?
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

selimkoc

byte yil:5;
    byte ay:4;
    byte gun:5;
    byte saat:5;  
    byte dakika:6;
    byte islem:2;   


toplam 27 bit. 4byte bilgi 32 bit eder. Dolayısı ile bu verinin uzunluğu 4 byte sığar.

Aynı hatayı alıyorum. Kullandığım platform Arduino 1.8.0


M_B

Hocam uC de denedim herhangi bir hata vermedi. Arduino da denemedim.
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

Klein

#7
Alıntı yapılan: selimkoc - 01 Ağustos 2017, 13:06:27
byte yil:5;
    byte ay:4;
    byte gun:5;
    byte saat:5;  
    byte dakika:6;
    byte islem:2;   


toplam 27 bit. 4byte bilgi 32 bit eder. Dolayısı ile bu verinin uzunluğu 4 byte sığar.

Aynı hatayı alıyorum. Kullandığım platform Arduino 1.8.0

Bit alanlar olduğunu farketmemişim.

union içerisindeki struct'a isim vermezseniz bazı platformlarda hata verir. Kullandığınız derleyicinin dokümanlarında "anonymous struct"  ararsanız gerekli direktifleri bulabilirsiniz. Ya da struct'a isim verin.

ya da daha önce önerdğim gibi 

tip x = *(tip *)&struct_ismi;

şeklinde işaretçi ile aktarabilirsiniz.

ya da doğrudan struct'ı eeproma yazmak için aşağıdaki gibi bir kod kullanabilirsiniz.
unsigned char *c = (unsigned char *)&struct_ismi; 
for(int i=0; i< 4; i++)
{
   eeprom_yaz(adres + i , *c++);
}


okurken de
unsigned char *c = (unsigned char *)&struct_ismi; 

for(int i=0; i< 4; i++)
{
   *c++ = eeprom_oku(adres + i);
}


baran123

Şöyle dene birde.

typedef union
{
    struct tarihSaat {
        unsigned yil:5;
        unsigned ay:4;
        unsigned gun:5;
        unsigned saat:5;  
        unsigned dakika:6;
        unsigned islem:2; 
        unsigned RESERVED:5;
    };

    struct tempData {
        unsigned long temp;
    };
}Datastruct_t;

int main() 
{
    Datastruct_t myStruct;
    long tempData; 
    
    myStruct.yil = 17;
    myStruct.ay = 7;
    myStruct.gun = 24;
    myStruct.saat = 12;
    myStruct.dakika = 50;
    myStruct.islem = 1;
    
    tempData = myStruct.temp;
    
    return (0);
}

muhittin_kaplan

#9
paketleyip saklayın

qeek

#10
Hocam şöyle bir şey denedim olmadı.
char *bb = "merhaba";

typedef struct{

    char me[2];
    char rha[3];
    char ba[2];
}Atama_t;

Atama_t atanan;

int main()
{
    atanan =*(Atama_t*)bb;
    printf("%s\n",atanan.me);
    printf("%s\n",atanan.rha);
    printf("%s\n",atanan.ba);
    printf("%s\n",bb);
}


Çıkış
merhaba
rhaba
ba
merhaba


Yukarda 3 tane yer ayırmama rağmen neden acaba sadece oraları almadı.

foseydon

#11
şu şekilde aktarabilirsiniz;

temp = 0;
temp |= zaman.yil;
temp <<= 4;
temp |= zaman.ay;
temp <<= 5;
temp |= zaman.gun;
temp <<= 5;
temp |= zaman.saat;
temp <<= 6;
temp |= zaman.dakika;


şu şekilde de aktarabilirsiniz;
unsigned long *ptr;
ptr = &zaman;
unsigned long x = *ptr;


birinci yöntem daha güvenilirdir. ikinci yöntem daha hızlıdır.

OptimusPrime

belirlemis oldugun yapi 27 bitlik 4 byte ediyor zaten. derleyici bu yapinin boyutuna 6 byte diyorsa paketlemeyi dene
__attribute__ ((__packed__))
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

bymrz

@geek ;


char *bb = "merhaba";

Aslında yukarıdaki gibi bir string tanımladığınızda, derleyici dizinin sonuna 0x00 karakterini ekler.
printf komutu da stringi yazarken 0x00 karakterini görene kadar yazmaya devam eder. Sendeki sorun bu yüzden.


[/size]atanan =*(Atama_t*)bb;
[/size]

Ayrıca bu komut ile bb stringini atanan dizinine aktarmış olmuyorsunuz. bb dizinin ilk byte'ının bulunduğu adres bilgisini "atanan" işaretçisine aktarıyorsunuz. Veriyi kopyalamıyorsunuz yani...

Klein

#14
Alıntı yapılan: alone_lover - 02 Ağustos 2017, 22:11:48
@geek ;

atanan =*(Atama_t*)bb;

Ayrıca bu komut ile bb stringini atanan dizinine aktarmış olmuyorsunuz. bb dizinin ilk byte'ının bulunduğu adres bilgisini "atanan" işaretçisine aktarıyorsunuz. Veriyi kopyalamıyorsunuz yani...

Hayır  tam aksi.  atanan değişkeninin veri büyüklüğü kadar veri değişkene aktarılır.

eğer atatan dipi işaretçi lsaydı ve baştaki '*' olmasaydı

atanan = (atanan_t *)bb;

şeklinde olsaydı o zaman adres atamasından bahsedebilirdik.