Reading 2 bytes the right way

I have a sensor that supplies its 16 bits like this: 1. MSB 2. LSB:

Values ​​are in this range:

0xffff ===> -32767   MIN 
0x8000 ====> -1 LSB say -1 
0x0000 ====> +1 LSB say 1 
0x7FFF ====> 32767 MAX 

      

I am trying to display these values ​​in a readable way. To do this, I wrote this little program:

#include <stdio.h>
#include <math.h>
#include <stdint.h>
int main(){
  char msbyte =0x7f;
  char lsbyte = 0xff;
  int16_t temp=0;
  temp = (msbyte<<8) | lsbyte;
  printf(" %4x temp %d ", temp,temp);

  return 0 ;

}

      

the result I am getting is weird:

ffffffff temp -1

I expected the result to be:

7fff temp 32767

What am I doing wrong?

+3


source to share


3 answers


Use the following:

uint8_t msbyte =0x7f;
uint8_t lsbyte = 0xff;

      

If char

behaves as signed char

in your implementation, lsbyte while oring expands the sign bit and the result may be unexpected. To solve the problem, you must use unsigned char

oruint8_t

Live demo

Regardless of this path, the output range will be:



0xffff ===> -1 
0x8000 ====> -32768
0x0000 ====> +1 LSB say 1 
0x7FFF ====> 32767 MAX 

      

If you really want the range as you pointed out, follow these steps: (Save msbyte and lsbyte unsigned

)

int16_t num16=0;
temp = (msbyte<<8) | lsbyte;
num16 = (int16_t)(temp & 0x7FFF);  /* Get the number */
if(temp & 0x8000) { /* Get sign bit */
  num16 = num16 * -1 - 1;
}

      

Live demo

+3


source


Edit:

char msbyte =0x7f;
char lsbyte = 0xff;

      

to

unsigned char msbyte =0x7f;
unsigned char lsbyte = 0xff;

      

char

is a signed type in your implementation and undergoes sign expansion when promoted to int

.



Also change:

printf(" %4x temp %d ", temp,temp);

      

to

printf(" %4x temp %d ", (uint16_t) temp,temp);

      

to avoid signed expansion if temp

negative.

0


source


As mentioned, your problem is that the most significant bit is being used as the sign bit.

You can avoid this by using:

uint8_t msbyte =0x7f;
uint8_t lsbyte = 0xff;
uint16_t temp=0;

      

Also, I find using the AVR type defs , Short tutorial useful when handling inline / device data.

For example, define:

typedef unsigned char BYTE
typedef unsigned int WORD

      

and use BYTE and WORD in your code.

0


source







All Articles