2008-08-04
Patch Level Update: PICC-18 STD
2008-07-29
Patch Level Update: HI-TECH C PRO for the PIC10/12/16 MCU Family
2008-07-21
NEW - PRO Compiler supporting Microchip PIC32 microcontrollers
Patch Level Update: PICC-18 STD
Patch Level Update: HI-TECH C PRO for the PIC10/12/16 MCU Family
NEW - PRO Compiler supporting Microchip PIC32 microcontrollers
Omniscient Code Generation: as featured in EDN Hot 100 Products of 2007.
|
The C language provides a number of built-in data types (int, float, etc.) to make various operations easier to program. You can also define your own types using struct, and define functions to perform operations on them. Note: typedef does NOT define a new type, merely a new name for an existing one. A future Tech Tip will discuss the definition of new types. Sometimes, however, you need to interact with the Outside World, and look behind the scenes at one of these objects. A common requirement is to split a 32-bit integer into four 8-bit integers for transmission over a data link, and reconstruct it at the other end. This can be simply done using the built-in bitwise and arithmetic operations:
unsigned long old = 0x12345678;
unsigned char c[sizeof(long)];
unsigned long new;
/* split up */
c[0] = old & 0xff;
c[1] = (old >> 8) & 0xff;
c[2] = (old >> 16) & 0xff;
c[3] = (old >> 24) & 0xff;
/* use c as an array of size (sizeof(long)) */
/* reconstruct */
new = c[0] |
(c[1] << 8) |
(c[2] << 16) |
(c[3] << 24);
This approach can't be used when you want to split up something that is not an integer - float, or a struct, for example. For these cases you would need to use one of several other methods, which include one of the only legitimate uses of a cast:
using_cast() {
float old = 1.2345;
unsigned char c[sizeof(float)];
float new;
int i;
/* split up */
for (i = 0; i < sizeof old; i++) {
c[i] = ((unsigned char *) &old)[i];
}
/* use c as an array of size (sizeof(float)) */
/* reconstruct */
new = *((float *) c);
}
You will see that this sample code first
and then
using_union() {
float old = 1.2345;
union { float f; unsigned char c[sizeof(float)]; } u;
float new;
/* split up */
u.f = old;
/* use u.c as an array of size (sizeof(float)) */
/* reconstruct */
new = u.f;
}
#include <stdlib.h>
using_memcpy() {
float old = 1.2345;
unsigned char c[sizeof(float)];
float new;
int i;
/* split up */
memcpy(c, old, sizeof old);
/* use c as an array of size (sizeof(float)) */
/* reconstruct */
memcpy(new, c, sizeof new);
}
This last example does almost the same thing as the first in this set of three, but uses the library memcpy() function instead of explicit casts and hand-coded copying. memcpy() and its companions treat whatever pointers they are handed as if they were arrays of unsigned char. Be wary when handling float or double values in this manner: some combinations of bits in the IEEE-754 floating point format do not represent actual values and performing any calculations on them will cause Bad Things to happen. (A future Tech Tip will discuss floating point values and operations in more detail). These techniques are only valid if the unsigned char arrays are not modified between splitting up and reconstruction, and where they are handed between programs compiled with identical options by the same version of the compiler.
|
Copyright © 2008 HI-TECH Software • Trademarks • Forum
Site Map