I have a union in a project i'm working on that represents a USB joystick report:
union {
struct{
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
};
uchar buffer[8];
} report;
this way i can easily put the values into the struct members and use the buffer member to send that data over USB, however I end up modifying this union for different projects (different resolutions on the axis, more/less buttons etc) so then i have to work out what the new size of the struct is to declare the array with the same size.
is there a way to automatically make the array the same size? i thought of using sizeof which requires me to change the struct like this:
union {
struct _data{ // either this
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
} data; // or this
uchar buffer[8];
} report;
but then i can no longer put data into the struct like this:
report.xaxis = value;
but instead:
report.data.xaxis = value;
which i don't want.
is there a way to do this cleanly?
Step 1 is to get a standard C compiler. Then you can use an anonymous struct. To get the appropriate size for the array, use a struct tag, which is only needed internally by the union.
typedef union {
struct data {
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
};
uint8_t buffer[sizeof(struct data)];
} report_t;
...
report_t r;
r.xaxis = 123;
You could use offsetof() for this with the last element in the struct
union
{
struct data
{
uint8_t xaxis;
uint8_t yaxis;
uint8_t xraxis;
uint8_t yraxis;
uint8_t zraxis;
uint8_t slider;
uint8_t buttons8;
uint8_t buttons16;
};
uint8_t buffer[offsetof(struct data, buttons16)+1];
} report;
The solutions other people have proposed here will work. However, they are all hacks, due to your use of a union for ease of conversion to bytes. There is a cleaner solution, which is to do away with the union. Simply make your struct the top-level type, and have your function that sends data over USB take parameters of (void * data, size_t length) . Then, you can easily send any data type over USB.
Related
I am trying to assign a string to a pointer which is in the structure. Even though, I am able to initialise the string to pointer successfully, when I try to use the string(access the pointer), I get some random values. How should I solve the problem. Following is my code:
typedef struct
{
uint8_t LOG_ID;
uint8_t timestamp;
uint8_t loglength;
uint8_t checksum;
uint8_t *payload;
} Log;
Log LB_t;
void main(){
LB_t.LOG_ID=1;
LB_t.timestamp=3;
LB_t.loglength=17;
LB_t.checksum=89;
LB_t.payload="LED initialised";
log_item(&LB_t,17);
}
void log_item(uint8_t *logptr,uint8_t length){
while(length!=0){
CB_buffer_add_item(tx,*logptr);
length=length-1;
logptr++;
}
}
Is there any alternate way in which I can access the pointer?
OK, I get it , you expect 'payload' to be inside the struct. Its not, just the pointer. You need to do this
typedef struct
{
uint8_t LOG_ID;
uint8_t timestamp;
uint8_t loglength;
uint8_t checksum;
uint8_t payload[100];
} Log;
and then
strncpy(LB_t.payload, "LED initialised", 100);
you probaly want to make the 100 a const or #define somehwere. And change yr 17 to sizeof(Log)
I would like to directly assign a byte array to a struct in C. The protocol looks like this(yes I know this is not compiling because flexlible arrays are only allowed as the last element of a struct)
struct telegram{
uint8_t controll;
uint16_t src_addr;
uint16_t dst_addr;
uint8_t is_group_addr :1;
uint8_t routing_cnt :3;
uint8_t data_len :3;
uint8_t data[];
uint8_t chksum;
};
how could I solve that? I like that I can directly access the field within the protocol very easy with a struct. The easy way would be to to say the last element of the data[] is the checksum, but I would like to know if there is a better/prettier way to do that.
I am using a union and an anonymous structure inside it. I want to know how I can initialize the structure members inside it. how can i do that? Please help :)
typedef union
{
uint8_t All;
struct
{
uint8_t G:1;
uint8_t O_B:1;
uint8_t Unused:1;
uint8_t W1:1;
uint8_t W2:1;
uint8_t Y1:1;
uint8_t Y2:1;
uint8_t IAQ:1;
};
} _UNION_VARIABLE;
_UNION_VARIABLE bit_field_array[5] = { {.G=1, .O_B=0, ...}, {.G=0, .O_B=1, ...},.....};
Is this correct?
I am using a union and an anonymous structure inside it. I want to know how I can access the structure member inside it. Like if i want to access G variable of structure using union variable then how can i do that. Please help :)
typedef union
{
uint8_t All;
struct
{
uint8_t G:1;
uint8_t O_B:1;
uint8_t Unused:1;
uint8_t W1:1;
uint8_t W2:1;
uint8_t Y1:1;
uint8_t Y2:1;
uint8_t IAQ:1;
};
} _UNION_VARIABLE;
I am getting compilation error for accessing structure member like below :
_UNION_VARIABLE sg_RefreshVar;
sg_RefreshVar.G = false;
Error :
#137 union "<unnamed>" has no field "G"
You need to give it a name
typedef union
{
uint8_t All;
struct
{
uint8_t G:1;
uint8_t O_B:1;
uint8_t Unused:1;
uint8_t W1:1;
uint8_t W2:1;
uint8_t Y1:1;
uint8_t Y2:1;
uint8_t IAQ:1;
} bit_field;
} _UNION_VARIABLE;
and then you can go
_UNION_VARIABLE.bit_field.G;
I have this union:
typedef union Message
{
message_base base;
message_with_parameters parameters;
reply_message reply;
buffer_t *buffer; // can't figure out what to put here
} message;
message_with_parameters has a message_base as the first field and reply_message has a message_with_parameters as as the first field which in turns has message_base as as the first field.
So basically I can access any of them and I'll still get all the data I need, however I am getting a buffer from my driver and now I want to serialize it into the message.
I already know that the pointer to the buffer is wrong as it won't correlate with my structs but I can't have a fixed size buffer.
Somewhere along the way I want to do this:
m->buffer = buff->payload;
And no matter what kind of data type I have, it will still serialize.
How can it be done?
EDIT:
Here are my structs:
typedef struct MessageBase
{
uint32_t u32DeviceID;
uint32_t u32CoreID;
uint16_t u16Class;
uint16_t u16CRC;
uint8_t u8OpCode;
void (*states [MAX_OPCODES]) (void *);
} message_base;
typedef struct MessageWithParameters
{
message_base base_class;
uint8_t u8Param1;
uint8_t u8Param2;
} message_with_parameters;
typedef message_with_parameters reply_message;
typedef union Message
{
message_base base;
message_with_parameters parameters;
reply_message reply;
} message;
its because the data in the buffer isn't part of the union.
buffer_t* buffer is a pointer, so the pointer is part of the union, not the data which it points at
you probablly want to do something like
m = (message*) buff->payload;