undran om en Union

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

undran om en Union

Inlägg av dangraf »

Jag skriver kod för att lagra data i ett eeprom minne.

Ibland måste jag spara och läsa en "header" som kan består av t.ex

float fvärde1; //4byte
float fvärde2; //4bute
long tid; //4byte
int adress; //2 byte

Eftersom jag får skicka/ta emot värdena i form av bytes till mitt eeprom så hade det varit göttit ifall jag kunnat göra en "union" eller liknande.

jag hade viljat ha det ung som

Kod: Markera allt


union
{
  struct{
     float  fvärde1;    //4byte
     float  fvärde2;    //4bute
     long  tid;           //4byte
     int    adress;      //2 byte
  }v;
  unsigned char c[14];

}u_test;
MEN!! Om man skriver som mitt exempel ovan, så måste jag skriva t.ex:

utest.v.fvärde1

för att komma åt mitt float värde1.

Går det att deklarera min "union" så att jag slipper "v"et och på så sätt få det snyggare?
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Ja, det ska gå (kanske beroende på din kompilator).

GCC stöder det iaf:

http://www.redhat.com/docs/manuals/ente ... ields.html

" For compatibility with other compilers, GCC allows you to define a structure or union that contains, as fields, structures and unions without names "

Alltså, du kan ha en struct utan namn i din union. Och delarna i structen kommer du åt som om de låg direkt i din union.
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

Det var så enkelt alltså :-) tackar!!
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Man kan även göra såhär:

Kod: Markera allt

  struct{
     float  fvärde1;    //4byte
     float  fvärde2;    //4bute
     long  tid;           //4byte
     int    adress;      //2 byte
  }v;
unsigned char Counter;
for(Counter = 0;Counter < sizeof(v);Counter++)
  {
  Save2EEPROM(*(char*)&v+Counter);
  }
Det betyder:
Värdet som den om-castade (address_till_v + Counter) pekar på hämtas och "Save2EEPROM" kallas med det värde. Den är lite tricky men fullt legal.
mindless
Inlägg: 2
Blev medlem: 30 juni 2005, 14:36:07

Inlägg av mindless »

Tänkte bara tillägga att en struct kan vara större än summan av dess fält, pga padding. Speciellt om man har korta sådana i mitten av en struct. Därför kan det skrivas onödig data till EEPROMet i bästa fall, eller att man missar att skriva hela structen i värsta fall.

http://www.lysator.liu.se/c/c-faq/c-9.html#9-10

Och även:
Har inte precedence reglerna i huvudet men tror det ska vara
Save2EEPROM(*((char*)&v+Counter));
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Anledningen till att jag skrev 'sizeof(struct)' är just att man inte ska räkna ut storleken själv, det tar kompilern hand om.

Sen har deklarationen av Save2EEPROM ju en roll också men det blir väldigt specifik då och det beror ju på hårdvara osv.

Jag använder denna deklaration:

Kod: Markera allt

void Write_EE_Buffer(unsigned int Address, unsigned char * XBuffer, unsigned int Length)
  {
  unsigned char Part;
  while(Length)
    {
    Part = 0x10 - (Address & 0x0F);
    if(Length < Part) Part = Length;
    Length -= Part;
    Write_EE_Enable();             /* Allow it to be programmed */
    EE_NCS = 0;                    /* Activate *CS */
    SPI_Write_Data(EE_WRITE); /* Command a WRITE */
    SPI_Write_Word(Address);  /* Send Address */
    while(Part)
      { /* While within one bank send data */
      SPI_Write_Data(*XBuffer);
      XBuffer++;  /* Point on next byte */
      Part--;    /* Count down */
      Address++; /* Count up address */
      }
    EE_NCS = 1;
    while(Read_EE_Status() & EE_S_WIP); /* Wait for bank to be finished */
    }
  }

När jag kallar den rutin anroper jag den via en enklare rutin:
void Save_Configuration(void)
  {
  Write_EE_Buffer(0,(byte*)&Config,sizeof(Config));
  }
så jag känner mig ganska säker på att jag har refererat rätt, det är fungerande kod, testat under en del år.
Skriv svar