Hi all, I'm new to C and need a hint on an optimization problem. I have a 16 bit counter, divided into two 8bit SFRs, let's say TH0 and TL0, and I want to transfer them to a short. I could: mshort = (short)TH0 * 256 + TL0 but this takes 16bytes, similar to something like: mshort = (short)TH0 << 8 + TL0 I would like to do it more simple, like: MSB of mshort = TH0 LSB of mshort = TL0 I tried it that way: unsigned short *pINT; pINT = &TH0; but this is not possible with SFRs. Something else I tried: unsigned short mINT; unsigned char *pChar; pChar = & mINT; *pChar = TH0; *(pChar + 1) = TL0; results in even more code (31 bytes) So I think it would be the easiest, if I could place 2 char variables at the same address, covered by my short, like: unsigned short mINT; unsigned char mChar[2] (at the same address like mINT) mChar[0] = TH0; mchar[1] = TL0; but I don't know, how to place the mChar array at the same address of mINT. I tried it with: unsigned char mChar[2] _at_ mINT; but this is not possible (compiler error). So anyone here, who could give me a hint how to place both variables at the same address? Thanks in advance Marco Della Rocca
So I think it would be the easiest, if I could place 2 char variables at the same address. You might want to refer to your C textbook on what a union is. That is what you are looking for.
I've been coding with C for around 10 years and don't think I ever used the keyword "short" before. "unsigned short mINT;" Is this a 16 bit value? If so, why not make it unsigned int mINT; The word "short" to me mentally implies an 8 bit variable. Sorry, Hate to be nitpicking but I prefer code that I understand right off the bat instead of having to pick up my C book (dont have it handy today anyway:) Ditto on checking out unions in C Andy
"The word "short" to me mentally implies an 8 bit variable." That's a bad implication. The Standard specifies that "short" have a minimum range of -2^15 to 2^15.
To be more precise, The Standard specifies that "short" have a minimum range of -32767 to 32767.
"Short" is a standard C type. Like the other C types, the actual width in bits of the type is implementation dependent. The standard tells you that: - a short is at least 16 bits wide - a long is at least 32 bits wide. - an int is at least as wide as a short and no wider than a long. Everything else is up to the implementation. Almost all embedded programmers I know adopt a local convention of typedefs that specify the exact width, e.g. typedef U8 unsigned char; typedef U16 unsigned int; typedef U32 unsigned long; typedef S16 signed int; typedef S32 long; so that they can remain platform independent. The C99 standard introduces a new header, <inttypes.h>, with standard names for these types, e.g. uint8_t uint16_6 The standard also adds some "half open" types with semantics like "any integer width you like as long as it's at least 16 bits wide". Other popular spellings include UINT8, UINT16, etc. You also see BYTE, WORD, DWORD, QWORD. I don't personally care for these because the width of a "word" is really hardware dependent. It's not always 16 bits, though that's what people using this series of names expect. Putting the actual number of bits in the type name is much more clear.
Hi, if the two SFRs are placed in contiguous addresses, you can just define an appropriate SFR16, e.g.:
sfr TL2 = 0xCC; sfr TH2 = 0xCD; sfr16 T2 = 0xCC;
if the two SFRs are placed in contiguous addresses, you can just define an appropriate SFR16, a very dangerous practice. Two years from now you will use another derivative where they are not "in contiguous addresses" and you will spend hours/days/weeks figuring out why this 'good' code suddenly does not work. This seems to be, based on reading some past posts, one of the bugs that are most difficult to catch for some. With an ICE it is no big deal. Erik PS in my opinion, SFR16 should be outlawed (it is here) for the above reason. Erik
you can just define an appropriate SFR16, Bad idea. Never define your own SFRs. That's what you get ready-made headers from Keil for.
That's what you get ready-made headers from Keil for. Which are sometimes woefully incomplete and/or just copied from a completely different device without modification *cough*ADuC845*cough*.
Bad idea. Never define your own SFRs. That's what you get ready-made headers from Keil for. I always do. The names, as they are, are not searchable, e.g. if you search on 'EA' you may miss IOR IE,080h. staying with the above example, my names are sfr SF_IE = 0xa8; sbit SB_IE_EA = 0x8f; #define SM_IE_EA 0x80 When you get to the derivatives with 'paged' SFRs such as SILabs f12x, it get even better. then I have SG_... //any sfrpage S0_... //SFRpage 0... Erik
typedef U16 unsigned int; Is only 16 bits in 8 to 16 bit compilers. In 32 bit compilers it will be 32 bits.
typedef U16 unsigned short int; Will give you 16 bits in many 32+ bit compilers. Some compilers only support 32 data.
Hi and thanks for your lightning fast answer,
that's exactly what I needed. Reduced the code down to 2 MOVes. Sorry for this newbie question.
Thanks for your efforts to help, anyway.
Thanks Tim,
this would have been the best solution for me (let it be good coding or not). Unfortunately there's another 8bit SFR between them (did not see this yesterday and thought they were contiguous).
I posted: "PS in my opinion, SFR16 should be outlawed (it is here)" now you post Unfortunately there's another 8bit SFR between them (did not see this yesterday and thought they were contiguous).
I take it that you now have joined the group outlawing them.
Erik