16 bit variable conversation to 8 bit variables

Discussion in 'Embedded Systems and Microcontrollers' started by ecka333, Dec 20, 2010.

  1. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    I am programming PIC16F876A microcontroller (8 bit). Compiler Mikroc from Mikroelektronika. I have unsigned int variable Clock, which is 16 bit long and i need to write it to eeprom. As i understand, i need to convert this variable to two 8 bit variables, then write them to eeprom.
    I am thinking to convert it in following way:
    ClockHigh=Clock/255
    ClockLow=Clock%255
    and then store ClockHigh and ClockLow to eeprom .
    When i need to retrieve variable Clock from eeprom, i am planning to use:
    Clock=ClockHigh*255+ClockLow
    Also i heard, that there is way to do all these conversations with shift operators >> and <<. I need most efficient way.
     
  2. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    I think a union would be best for you in this case. Be very careful with division and multiplications then working with C and MCUs. However compilers are quite smart so it could be that your compiler understand what really want to do.
    Code ( (Unknown Language)):
    1.  
    2. typedef union
    3.    {
    4.    unsigned short counter;
    5.    signed char hilo_bytes[2];
    6.    } clock_register;
    7.  
    8. clock_register clock;
    9. // play with variable clock
    10. clock.counter = 0xffff;
    11.  ADDH = hilo_bytes[0];
    12.  ADDL = hilo_bytes[1];
    13.  
     
  3. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Hmm.. Can you explain your code a little?
     
  4. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
  5. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Roughly, A union is a way to create a new datatype, such as int, string, etc, but of the design you need. Compilers are generally very good at figuring out "what you meant" when using them, while attempting the same in assembly is a bit of a pain.
     
  6. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Actually it's a lot easier in assembler because clock is already two 8 bit files. It's manipulating 16 bit numbers which is harder........ but I digress.
     
  7. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    The / operator can be inefficient.

    You can do this very easily with the & and the >> operator. This would break up a 16 bit variable into two 8 bits variables.
    Code ( (Unknown Language)):
    1.  
    2.   unsigned char loByte;
    3.   unsigned char hiByte;
    4.   unsigned int i = 0xff02;
    5.  
    6.   loByte = i & 0x00ff;
    7.   hiByte = i >> 8;
    8.  
     
  8. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Ok, thanks you, spinnaker. I think your method should work, i will try this today or tommorow.
     
  9. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    ups...but how i can join these 8 bit variables to one again?
     
  10. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    It is here the union comes handy as the members that compose a union all share the same storage area within the same memory. Take a look at my code. Some notes my compiler use Little-endian then formatting numbers. I do not know the endianess for your compiler. If it use Big-endian the hi and low byte will be swapped.
    Code ( (Unknown Language)):
    1.  
    2. [SIZE=2]typedef union
    3. {
    4. unsigned short counter;
    5. signed char hilo_bytes[2];
    6. } clock_register;
    7. clock_register clock;
    8. // play with variable clock
    9. void main()
    10. {clock.counter = 0xffff;
    11. TMR1L = clock.hilo_bytes[0];
    12. TMR1H = clock.hilo_bytes[1];
    13. //some time alter
    14. clock.hilo_bytes[0]=TMR1L;
    15. clock.hilo_bytes[1]=TMR1H;
    16. //Now the variable clock.counter will contain the TMR1 value read above
    17. }
    18. [/SIZE]
     
  11. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    I cant use TMR1 registers, because TMR1 is used for time counting.
     
  12. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    The TMR1 was just an example. You can use any 8 bit register you want in any mix:rolleyes:
     
  13. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,866
    988

    Just do the opposite

    i = (hiByte << 8) | loByte;
     
  14. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    My BoostC compiler automatically generates the correct single word instructions when I use the following macros;

    Code ( (Unknown Language)):
    1. #define lo(x) (char)((x)&0xFF)
    2. #define hi(x) (char)((x)/256)
    Happy Holidays.

    Cheerful regards, Mike
     
Loading...