Working with bytes and bits

I'm writing a program (to be more exactly it's a DLL) that comunicates with some machines through the serial port, so I need to read 17 bytes from the buffer, get the first byte and split it into 7 bits (the serial port configuration specifies that will be 7 the number of data bits).

- How can I get this value from the BYTE array and split it into an array of bits

- I'm getting the value from a position of the BYTE array a writing to a file to see what the program(VB6) is receiving. The first time it receives only one byte, the other times, it receives the whole BYTE array. Why

I'm using fputs like this:

char cSWA = buf[0];
fputs(&cSWA, mFilePointer);

- And, how can I convert a BYTE array to a char type

- And the last one, how can I convert from unsigned char to const char




Answer this question

Working with bytes and bits

  • xlthim

    Can you explain how your code works

    I think that you are moving between memory positions, but why 0x07, 0x18 and so on



  • Aaronru

    If the byte is sent to you as '(', you'll receive it as '(', regardless of the number of bits used to encode it on the serial port transmit data line. Configuring the serial port to 7 bits just determines how many bits are used in the frame, the stream of bits on the line. There are additional bits in a frame: start bit, stop bit, parity bit. The serial port device driver hides all this from you. It strips off the start, stop and parity bit and converts the 7 data bits to an 8 bit byte.


  • Paul Farrell

    Jonathan, the machine that sends the data through the serial port works like this:

    byte 0 - indicates the beginning of the instruction
    byte 1 - StateWord A
    byte 2 - StateWord B
    byte 3 - StateWord C
    bytes 4,5,6,7,8,9 - Weight to Display
    bytes 10,11,12,13,14,15 - Tara
    byte 16 - Carriage Return
    byte 17 - CheckSum

    Each bit of the StateWords (A, B and C) have their meanings.

    I only need to check StateWord A.

    The byte 1 (StateWord A) works like this (I'm showing how the program should consider the data):

    bits 6, 5 - Always equal to 0 (zero)
    bits 4,3 - Seed Value
    bits 2,1,0 - Decimal Point

    Example:

    1101101
    The Seed Value is 01 that corresponds to x = 1(this value is from a protocol table that I have), and the decimal point is selected by the combination 101, that corresponds to 0.00x. So I will multiply a value that I have on positions 4 to 9 with 0.001.

    But I don't know how can I convert this unsigner char to a bit array or sequence so I can check the configuration about SeedValue and Decimal point.

    Did you understand now

    I've tried using:
    unsigned char SWA = buf[0];
    char *bits;
    itoa(atoi((char*)SWA),bits,2);

    But didn't work.



  • Vishal Aggarwal

    I really don't understand your question. If you have an unsigned char (the usual representation in C and C++ of a byte) the bit sequence it has it is its value: there is no need to check each individual bit you just need to check the value. Are you looking for one specific value, or a range of values, or do you just need to check if a specific bit is set or not set Maybe if you explained what you are trying to do with the byte the question might become clearer.

  • cx409

    I'm having trouble too. First off, google for 'ascii table'. Each character has an encoding in bits. Say you want to check if you received a '('. The bits for that character are 00100100 in binary, 40 in decimal, 0x28 in hexadecimal. You can use any of the following if statements:
    if (buf[0] == 0x28)
    if (buf[0] == 40)
    if (buf[0] == '(')

    The last one would be the more readable one of course. Even if you have configured the serial port for 7 bits, you'll still get 8 bits from the device driver (i.e: 00100100, NOT 0100100). The 8th bit is just always zero.



  • SamerAZ

    It is 7 bits on the serial port line but you'll get a full BYTE from the device driver so there's no need to convert. You can't predict how many bytes you'll get on the first call to ReadFile(), just keep reading until you get the full 17 bytes. Your call to fputs() is problematic, it expects a zero-terminated string. Try this:
    buf[17] = 0;
    fputs((char*)buf, mFilePointer);

    BYTE is typedef-ed to unsigned char. You can convert to char with a typecast:
    BYTE buf[18];
    const char* bufaschar = (char*)buf;

    There's no need to convert to const if you pass a char* as a function argument that is declared as const char*, C++ does it automatically without complaining.


  • Mumshelp

    When working with bits you really need to understand how hexadecimal works.

    In the description you said the the decimal point was control by bits 0, 1, and 2 so to get the value represented by just these bits you need to mask them. So you create a bit mask (which for ease of use is usually done in hexadecimal). Bit 0 is represented by 0x01, bit 1 by 0x02 and bit 2 by 0x04. If you then add these values together you get 0x07. You then bitwise-and then whole byte with this bitmask and the result is the value of just these 3 bits.



  • Remy Duchet

    But how can I get a BYTE and split into BITs

  • Soaring Skies

    Understood. Thanks.

    But another question...

    I tried before another way, I've set the value of an int variable to the unsigned char value, so I got its decimal value, and after this I've used the itoa() function, but it returns me a 6 positions binary number to a char pointer.

    How can I add just before the existing 6 positions, another 2 values to complete the bit array (8 bits for each byte)

    I've tryed
    *bitSWA = "00" + *bitSWA;

    But it's not right.
    How can I do this



  • lchristensen

    The constants 0x07 etc are "bitmasks" for the & (bit-wise AND) operator. Your status byte is encoded as 0zzssddd. To get the decimal point, you need to mask out all bits but "d". Just AND with 00000111 which is 0x07 in hexadecimal. To get the seed, you need to first mask out the "s" bits; AND with 00011000 (=0x18) which gets you 000ss000. Then you need to shift the bits to the right by 3 to get 000000ss, thus ">> 3".

    Same story for shouldbezero, first AND with 01100000 (=0x60) which gets you 0zz00000, then shift to the right by 5.

    Use Windows' calculator to convert from bits to hex: View + Scientific, click "Bin", type your bits, click "Hex".


  • MarcoL

    OK, I get it now:
    int decimalpoint = buf[1] & 0x07;
    int seedvalue = (buf[1] & 0x18) >> 3;
    int shouldbezero = (buf[1] & 0x60) >> 5;


  • M-Force

    Ok, the only question I have now is, how can I get an unsigned char variable (it receives the first position of a BYTE array) and find which BIT sequence does it represent.



  • yyjjtt

    I need to check bit by bit.

    Example:

    I receive the data like "(", it represents a hex number (I don't know which hex it represents), so I need to check each position.

    1101101 - This is the bit array

    6543210 - This is the ordenation of the bits

    I need to get the value of each position of that array.



  • Matt_Bruce

    Its simple arithmetic with the & and| operator.

    Each BYTE as 8 bits, each bit can be checked with a & operation. Or you can check bit combinations.

    Please get closer to you main problem



  • Working with bytes and bits