|
|
View previous topic :: View next topic |
Author |
Message |
James B Guest
|
Possible to use partial 16it Ints in a struct ? |
Posted: Mon Mar 06, 2006 1:27 pm |
|
|
I have a message coming from I2C from another PIC that has 8 bytes in it, split into 4 16bit signals, the first 5 bits are unused, the next is the sign bit, then 10 bits for the actual signal.
The binary looks like this:
00000 1 0000111100 == +60
I want to use structs to easily use these.
struct MySignal {
int16 signal:10;
int1 signbit:1;
int void_rest:5;
};
I get the compiler error "Number of bits out of range".
If this doesn't work, is it possible for me to split up an int16 ??? |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Mon Mar 06, 2006 1:53 pm |
|
|
The error is because you can only use the " : " to break down a int8 value.
Soooo.. If I were you I would use shifts and masks to make the value.
Code: | void main(void)
{
int32 temp;
int16 signal;
int1 sign;
sign=(temp&0b0000010000000000)>>11;//mask off all but sign and shift it
signal=temp&0b0000001111111111;//mask off all but signal
fprintf(DEBUG,"%u %lu!\n\r",sign,signal);
while(1)
{
}
}
|
or you could make a signed int16.. make signal and sign as above and do a
if (sign) signal*=-1; |
|
|
James B Guest
|
Oh, |
Posted: Mon Mar 06, 2006 2:00 pm |
|
|
Well, that solves that.
I was hoping to avoid int32 and shifts, it seemed a struct would faster. Esp. since this is going to be a very repetitive move. And my micro is running pretty slow to save power.
Too bad the : doesn't work for int16. |
|
|
James B Guest
|
|
Posted: Mon Mar 06, 2006 4:19 pm |
|
|
Ok, I settled on the fact I'de have to shift the data around, but now I'm having a similar problem with my pointer / struct. This is a little of topic with my last post but.....
The one I posted before just had 2 bytes in it, but my real one setup has two different stucts of 8.
My idea was to use the values returned by my getd(int *data, &type) function and apply whatever struct was appropriate. For example
This are my two structs :
Code: |
struct Signal_Type1 {
int16 data1;
int16 data2;
int16 data3;
int16 data4;
};
|
and
Code: |
struct Signal_Type2 {
int8 data1;
int8 data2;
int8 data3;
int8 data4;
int8 data5;
int8 data6;
int8 data7;
int8 data8;
};
//and then the pointers....
struct Sinal_Type1 *ptr1;
struct Sinal_Type2 *ptr2;
|
When I read in data of type2 I wanted to set a pointer to the data and then I could access the values in data with something like "ptr2.data5=x" which modifies some of data. This all really so I can addess data elememts by meaningful names.
But for the live of me I can not figure out the syntax for this.... If I can't figure it out in a bit I'll make a post about it.
Thanks |
|
|
Guest
|
|
Posted: Mon Mar 06, 2006 4:24 pm |
|
|
It is worth perhaps looking at some other ways of doing this. For instance:
Code: |
#define SIG_MASK (0x3FF)
#define SIGN_MASK (0x400)
int16 value;
int1 sign;
int16 signal;
//To save signal
value = (value & SIGN_MASK)|signal;
//To retrieve signal
signal=value & SIG_MASK;
//To set sign
value = value | SIGN_MASK;
//To clear sign
value = value & SIG_MASK;
//To get sign
sign = value && SIGN_MASK;
|
These involve no rotations, and will be pretty much what the compiler would have to code to handle an int16 bit access mode. They should be only a handful of instructions each.
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Mon Mar 06, 2006 4:37 pm |
|
|
Beware, that array operations (and pointers), take a relatively large number of operations...
Your declaration syntax should be OK, except the declaration you have posted, has the structure name misdeclared. To access an element in a pointer to a structure, use the '->' declaration, instead of the '.' declaration. You also need to actually declare the structure somewhere, and set the pointer to address it. So:
Code: |
struct Signal_Type2 {
int8 data1;
int8 data2;
int8 data3;
int8 data4;
int8 data5;
int8 data6;
int8 data7;
int8 data8;
};
//You need to actually _declare_ the structure. So far you have only created a name.
struct Signal_Type2 second_struct;
//Alternatively make a space the size required, using the memory
//access functions.
//Now make your pointer.
struct Signal_Type2 *ptr2;
//Now in the main code, make the pointer access the physical structure
ptr2=second_struct;
//Then you can access an element as:
second_struct.data8
//or as
ptr2->data8
|
Best Wishes |
|
|
James B Guest
|
|
Posted: Mon Mar 06, 2006 5:24 pm |
|
|
I see now, except for one thing. I'm doing this so that I can always use my getd(*data) which returns my *data with 8 new elements and also link structs to it so that I can access the vars by name.
I kind of want to link multiple structs to the same changing data. If that makes any sense.
For example:
getd(data,type);
if (type ==2)
second_struct.data1 = 250;
else
first_struct.data1 = 65000;
I'm not sure but I don't 'think' this would be very memory or cpu intensive. |
|
|
James B Guest
|
|
Posted: Mon Mar 06, 2006 6:52 pm |
|
|
I guess so imagine I have two structs and 1 source of data coming in. I want to link both so that I can do this:
struct animals {
int pig;
int cow;
int horse;
int duck;
}
struct equipment {
int tractor;
int truck;
int16 pipes;
}
int *data[8];
...
getd(data,type);
...
if (type == animals)
d = animals.duck;
else
p = equipment.pipes
...
So basically my data is always stored in the data[] but I can symbolicly access it by its type.
I dumbed down the example (obviously) to explain myself better. I'de rather not change the way I collect data in the getd().
This seems like a job for unions but I'm not sure how to aligh to an array multible times.
Thank You, |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 07, 2006 3:25 am |
|
|
Linking different names, is definately a name for unions.
Basically, if you declare two structure 'names':
Code: |
struct struct1 {
//stuff here
}
struct struct2 {
//other stuff here
}
//Then if you declare a union:
union union_name {
struct struct1;
struct struct2;
}
|
You can now use a union declared as 'union_name', to access the data through the two different structure names. Space will only be allocated to the union (just as with the structure), when you have a 'variable name', after the declaration. The actual amount of space allocated will be that of the larger structure.
Remember that you could allocate the 'space' somewhere else, either usng the memory management functions (include 'stdlibm.h', and using malloc), or by just allocating a byte array of the required size. If the memory is static, then you only need to pass the pointer, and declare the value passed as a pointer to a union of this type (don't actually 'move' the values). Now you can 'depointer' with the * declaration.
So if you have a function 'fred', returning a variable of type *union union_name, and you put this into 'mem_ptr', you can access the structures as:
(*mem_ptr).struct1.structure_element
Note the brackets. These are required, because of the way operator precedence works in C. 'mem_ptr', is a pointer to union of type 'union_name, and (*mem_ptr), is the union itself.
Best Wishes |
|
|
James B Guest
|
|
Posted: Tue Mar 07, 2006 3:50 am |
|
|
Thank You Ttelmah
I get it, but it seems I am making the program more complex then it needs to be. I was just looking for an easy way to call data by symbolic names but for as much as I'm doing that I may as well just hardcode it in (x = data[5])
It won't be as easy to read and I'm sure to forget thing here or there but it does keep it simple.
Thanks Again! |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Tue Mar 07, 2006 9:16 am |
|
|
Quote: | It won't be as easy to read and I'm sure to forget thing here or there but it does keep it simple. |
Put in LOTS of comments.
And Yes allways think of KISS. |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 07, 2006 9:56 am |
|
|
For some types of operation, the union/structure approach, may be the 'best', but for many (most?) likely embedded applications, careful use of your own direct accesses, and good comments will be better/simpler.
One thing it might be worth considering, is use of the #define.
So:
Code: |
#define pig 0
#define cow 1
#define horse 2
#define duck 3
#define tractor 0
#define truck 1
#define pipes16 1
#union {
b8[4];
w16[2];
} data;
|
Then you can access 'cow', as data.b8[cow], and 'pipes', as
data.w16[pipes16].
I use the '16', and '8', to remind you which data sizes are being used.
This has the advantage of being a lot less likely to cause compiler problems than the union of structures, but still give some 'sense' to the names.
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 07, 2006 10:20 am |
|
|
It would help if I had an int8, and int16 declarations in the union. Brain elsewhere...
Best Wishes |
|
|
James B Guest
|
|
Posted: Tue Mar 07, 2006 11:42 am |
|
|
I thought about define and didn't really cling to that since I'de be calling from an array, and like you said that adds a few instructions. I was looking at your post and was like "Huh.... apparently you don't need to give it a data type there", but then came to my senses with your last post
I did have an idea that isn't exactly what I wanted to do but.. How about declaring a *data[8], then assigning certain bytes inside it, based on thier memory
Sort of like the #byte command, but is it then required for me to locate *data?
ie:
int *data[8]; //lets say it starts at 0x100;
int &pig = 0x103;
int16 pipes = 0x101;
I figure when I update data it will only be meaningfull depending on the address/name I use, which is kind of what I wanted in the first place, but not really, I'm dumb so I'm comprimising.
Can I do that ? Also, can it be done without having ME locate *data? Or is this a waste of resources ? |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 07, 2006 3:28 pm |
|
|
If you access a _constant_ element in an array, the compiler sorts it all out at compile time, and directly accesses the element (only a couple of instructions). If you use a pointer, or a variable, the maths has to occur at runtime. Hence the define gives quick accesses, but using a pointer doesn't.
Sorry...
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|