Search code examples
type-conversionstructure9-bit-serial

C How can I write a value to an entire data structure, rather than just an element?


I am attempting to write a little C test program for reading data from a vending machine. I have the circuit hooked up, now the hard part is the code. The machine uses UART that calls for 9 total data bits. Here is my code. Attempting to write directly to the full 9 bit data type does not work, but writing to an element of it does.

struct nineBit {        //To make 9 bit character types for an array.
unsigned int data : 8;  //8 data bits.
unsigned int mode : 1;  //1 'mode' bit.
} data[35];             //Make an array of 9 bit data to store the incoming data block.

void setup() {
Serial1.begin(9600, SERIAL_9N1);  //Start the UART.
}

void loop() {
data[0] = Serial1.read();  //Works if 'data[0].data is entered instead.
                           //How can I transfer this all in one command?
}

Errors are rx.cpp: In function 'void loop()': rx.cpp:11:12: error: no match for 'operator=' (operand types are 'nineBit' and 'int') void setup() { ^

rx.cpp:11:12: note: candidates are:
rx.cpp:1:8: note: nineBit& nineBit::operator=(const nineBit&)

    ^
rx.cpp:1:8: note:   no known conversion for argument 1 from 'int' to 'const nineBit&'
rx.cpp:1:8: note: nineBit& nineBit::operator=(nineBit&&)
rx.cpp:1:8: note:   no known conversion for argument 1 from 'int' to 'nineBit&&'
make[1]: *** [../build/target/user/platform-6rx.o] Error 1
make: *** [user] Error 2
Error: Could not compile. Please review your code.

Solution

  • I assume you are using arduino or something similar. So Serial1.read() returns char. char is a signed 1 byte (8 bits) field. And your struct nineBit has 9 bits. How do you expect of writing 8 bits to 9 bited structure?

    A note about your structure: it doesn't have size equal 9 bits. Instance of any variable can have size evaluated in bytes only. So if you want to store 9 bits you have to create a two byted structure or more.

    And in fact sizeof(nineBit) equals 4 because your bit field have unsigned int type. If you want to reduce size of your structure you have to change bit field type to either short or char.

    Let's assume your serial transports two bytes per every structure. So you have to read two bytes and then assign them:

    struct nineBit {        
        char data : 8;  //8 data bits.
        char mode : 1;  //1 'mode' bit.
    } data[35];             
    
    void setup() {
        Serial1.begin(9600, SERIAL_9N1);  //Start the UART.
    }
    
    void loop() {
        char byte1=Serial1.read();
        char byte2=Serial1.read();
        data[0].data=byte1;
        data[0].mode=byte2;
    }
    

    If you want to use only a single line you have to write a C function or overload operator= if you use C++.

    C way

    struct nineBit {        
        char data : 8;  //8 data bits.
        char mode : 1;  //1 'mode' bit.
    } data[35];    
    
    void writeToNineBit(struct nineBit *value){
        char byte1=Serial1.read();
        char byte2=Serial1.read();
        value->data=byte1;
        value->mode=byte2;
    }
    
    void setup() {
        Serial1.begin(9600, SERIAL_9N1);  //Start the UART.
    }
    
    void loop() {
        writeToNineBit(data+0);   // or &data[0]..  0 is an index in array..
    }
    

    C++ way

    struct nineBit {        
        char data : 8;  //8 data bits.
        char mode : 1;  //1 'mode' bit.
    
        //    assume you have to assign data without mode..
        nineBit& operator=(char b){
            this->data=b;
        }
    } data[35];    
    
    void setup() {
        Serial1.begin(9600, SERIAL_9N1);  //Start the UART.
    }
    
    void loop() {
        data[0]=Serial1.read();    //  now it works cause you have operator overloading in your structure..
    }