我有一个以这种方式提供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
我做错了什么?
答案 0 :(得分:3)
使用以下内容:
uint8_t msbyte =0x7f;
uint8_t lsbyte = 0xff;
如果char
在您的实现上表现为signed char
,则lsbyte在oring时会扩展符号位,结果可能是意外的。要解决此问题,您应该使用unsigned char
或uint8_t
虽然这样,但输出范围是:
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;
}
答案 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 defs,Short tutorial非常有用。
例如,定义:
typedef unsigned char BYTE
typedef unsigned int WORD
并在代码中使用BYTE和WORD。