以正确的方式读取2个字节

时间:2015-04-23 12:26:40

标签: c

我有一个以这种方式提供16位的传感器:1。MSB 2. LSB:

值在此范围内:

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

我试图以可读的方式显示这些值。为此,我写了这个小程序:

#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 ;

}

我得到的结果很奇怪:

  

ffffffff temp -1

我希望输出为:

  

7fff temp 32767

我做错了什么?

3 个答案:

答案 0 :(得分:3)

使用以下内容:

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

如果char在您的实现上表现为signed char,则lsbyte在oring时会扩展符号位,结果可能是意外的。要解决此问题,您应该使用unsigned charuint8_t

Live demo

虽然这样,但输出范围是:

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

如果您真的想要指定范围,请执行以下操作:(保留msbyte和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

答案 1 :(得分:0)

变化:

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

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

char是您实施时的已签名类型,并在升级为int后会进行签名扩展。

同样改变:

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

printf(" %4x temp %d ", (uint16_t) temp,temp);
如果temp为否定,则

以避免签名扩展。

答案 2 :(得分:0)

如上所述,您的问题是高位被用作符号位。

您可以使用以下方法避免这种情况:

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

此外,我发现在处理嵌入式/设备数据时使用AVR type defsShort tutorial非常有用。

例如,定义:

typedef unsigned char BYTE
typedef unsigned int WORD

并在代码中使用BYTE和WORD。