简体   繁体   中英

Arduino - how to feed a struct from a serial.read()?

I am a beginner and I am trying to feed a struct table with 4 members typed BIN with a pointer, then send them to another one, serial2. I fail to do so.

I receive 4 chars from serial1.read() , for example 'A' '10' '5' '3'. To decrease the size of the data, I want to use a struct:

struct structTable {
  unsigned int page:1; // (0,1)
  unsigned int cric:4; // 10 choices (4 bits)
  unsigned int crac:3; // 5 choices (3 bits)
  unsigned int croc:2; // 3 choices (2 bits)
};

I declare and set: instance and pointer

struct structTable structTable;
struct structTable *PtrstructTable; 
PtrstructTable = &structTable;

Then I try to feed like this:

for(int i = 0; i<=4; i++) {
  if(i == 1) {
    (*PtrProgs).page = Serial.read();
  if(i == 2) {
    (*PtrProgs).cric = Serial.read();

And so on. But it's not working...

I tried to feed a first char table and tried to cast the result:

(*PtrProgs).page = PtrT[1], BIN;

And now, I realize I can not feed 3 bits in one time! doh! All this seems very weak, and certainly a too long process for just 4 values. (I wanted to keep this kind of struct table for more instances).

Please, could you help me to find a simpler way to feed my table?

According to the Arduino reference I just looked up Serial::read , the code returns data byte-by-byte (eight bits at a time). So probably you should just read the data one byte (eight bits at a time) and do your unpacking after the fact.

In fact you might want to use a union (see eg this other stackoverflow post on how to use a union ) so that you can get the best of both worlds. Specifically, if you define a union of your definition with the bits broken out and a second part of the union as one or two bytes, you can send the data as bytes and then decode it in the bits you are interested in.

UPDATE

Here is an attempt at some more details. There are a lot of caveats about unions - they aren't portable, they are compiler dependent, etc. But this might be worth trying.

typedef struct {
  unsigned int page:1; // (0,1)
  unsigned int cric:4; // 10 choices (4 bits)
  unsigned int crac:3; // 5 choices (3 bits)
  unsigned int croc:2; // 3 choices (2 bits)
} structTable;

typedef union {
  structTable a;
  uint16_t b;
} u_structTable;

serial.Read(val1);
serial.Read(val2);

u_structTable x;
x.b = val1 | (val2<<8);
printf("page is %d\n", x.a.page);

You can only send full bytes over the serial port. But you can also send raw data directly.

void send (const structTable* table)
{
    Serial.write((const char*)table, sizeof(structTable));  // 2 bytes.
}

bool receive(structTable* table)
{
    return (Serial.readBytes((char*)table, sizeof(structTable)) == sizeof(structTable));
}

You also have to be aware that sizeof(int) is not the same on all CPUS

A word about endianness. The definition for your struct for the program at the other end of the serial link, if running on a CPU with a different endianness would become:

struct structTable {
  unsigned short int croc:2; // 3 choices (2 bits)
  unsigned short int crac:3; // 5 choices (3 bits)
  unsigned short int cric:4; // 10 choices (4 bits)
  unsigned short int page:1; // (0,1)
};

Note the use of short int, which you can also use in the arduino code to be more precise. The reason is that short int is 16 bits on most CPUs, while int may be 16,32 or even 64 bits.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM