Copy some bits of a byte into an integer

Hi i have read with an SPI 2 bytes of data coming from a sensor. But the sensor only sends 11 bits so the last 5 bits of the second byte are useless. Also the first bit of the first byte indicate the sign of the number +/- so i dont want it. Is there any way to copy 7 bits of the first byte + 3 bits of the second byte in an integer variable to get only the absolute value?

Please provide specifications and data of the sensor. Then I will explain bit masking to you.

Also, your comment about the sign of the number is troublesome. Usually a signed to unsigned number conversion is "virtual" within the positive range of the signed number - in other words, the value is the same for both signed and unsigned representations. So, I'm suspicious of what you are up to with that, and it is another reason why I need to see the sensor spec.

@anon57585045 Its a thermistor to digital converter called MAX6682MUA+T

Link to datasheet please.

1 Like

Please don't force us to do research online. You are supposed to do the work and post either a link or the data.

1 Like

https://www.analog.com/media/en/technical-documentation/data-sheets/MAX6682.pdf

sorry

Have you tried doing the SPI read of both bytes at the same time into a uint16_t variable and just masking off the upper 6 bits?

1 Like

Where’s your code? It might be as simple as

  x=x>>5;

The data comes MSB first:

Read the following excerpts taken from data sheets and then learn through practice the procedures of converting raw bits into decimal temperature.



Yes, or just doing a SPI read into a signed 'int', shift left 5 times to place the MSB in the 'int' sign bit, then do a signed division by 32 to perform sign extension and restore the correct scale. But the bits come out MSB first, so this is not right, see below

If you don't need signed values, there is no additional processing needed, simply reading in from the SPI is enough.

because

the last 5 bits of the second byte are useless

The first SPI read will input B10-B3. The second will read B2-B0 and 5 more "useless bits".

If you read those into an integer that way, the sign bit will already be in the correct position and you can get a correct signed value with a simple signed arithmetic divide by 32.

I'm always nervous about bit shifting signed values as it's not clear to me such operations are well-defined.

See my updates. No shifting is required or really appropriate. If the device sends MSB first, after 16 SPI clock cycles (two SPI peripheral reads), the sign bit will be in the right position for a 2's complement value.

It's just too big, needs to be scaled down by 32 (by signed division, not shifting). That also throws away the 5 "useless bits". Sign extension is automatic if it's an 'int'.

Why not shifting? Sign extension of shifting is automatic if it is an int, (or other signed types like a int32_t or a int8_t.)

Heh. Probably why @gfvalvo is "nervous". Because people might shift something, not expecting sign extension to happen. Learn something new every day.

It's not clear to me that's the case. I've seen references to shifting of signed ints being implementation-defined or even undefined. I haven't bothered running down the official specification on this, I just don't do it.

One thing for sure, integer division will perform sign extension. Usually, the compiler will optimize something like that (power of 2 division) to a sign extended shift anyway.

Also, division follows the semantics, we're scaling a signed value. We don't really care about the bits.

Ah--learned something new. The issue is rounding down versus rounding towards zero:

Back to the OP. Why don't you want the sign? It maintains continuity in the temperature range. Are you trying to over-ride it just because it confuses you? What is the reason?

If you're only interested in a certain temperature range, can you not just perform input validation checks on it, prior to use? You can rule out negative numbers with a simple

int reading = getSensorValue();
if (reading >= 0) {
... do your stuff
{
else
{
  ...error or ignore reading
}

but as I implied, you can set the thresholds for a valid reading at any value, not just 0. So it depends on the application. Can you tell us about that?

1 Like

Given the following SPI acquired two bytes data:

byte highEight = 0b11111001;
byte lowEight  = 0b10100000;

How to find -6.375 from the above data bytes referring to information of post #10?
Solution by Brute Rule. The OP @lucasaenz may find it helpful.

byte highEight = 0b11111001;
byte lowEight  = 0b10100000;

void setup()
{
  Serial.begin(9600);
  unsigned int x = 0;
  for (int i = 0, j = 8; i < 8; i++, j++) //forming: 1111100110100000
  {
    bitWrite(x, i, bitRead(lowEight, i));
    bitWrite(x, j, bitRead(highEight, i));
  }
  Serial.println(x, BIN);  //debug point :1111100110100000
  x = x >> 5;
  Serial.println(x, BIN);  //debug point : 0000011111001101
  int value = bitRead(x, 10) * (-1024);  //positional weight of sign bit 
  bitClear(x, 10);  //sign bit is made 0
  value = value + x;  //value = -1024 + 0x3CD = -1024 + 973 = -51
  Serial.println((float)value * 0.125, 3); //shows: -6.375
}

void loop()
{

}

The Intelligent Rule based on post #13 @anon57585045 is under investigation.