我正在和几个朋友一起做一个项目,我正在尝试解决从 I2C 压力传感器读取数据时遇到的问题。
所附的代码是我遇到的问题的负责人。我正在使用的压力传感器的数字计数范围为 81 到 16128。当从传感器读取原始数据时,变化为 256(1 字节),因此从 8017 到 8273 到 8529,而不是像 8017 到 8018 等那样逐个数字. 因此,函数(值)不会像预期的那样平滑地变化。关于为什么在 256 次计数后每次都这样计数的任何想法?似乎由于某种原因它一口一口地改变(1000 0000)。
void get_inputs(void)
{
I2C_Master_Start();
I2C_Master_Write(0x50);
I2C_Master_Write(0x01);
I2C_Master_RepeatedStart();
I2C_Master_Write(0x51);
rawHighByte = I2C_Master_Read(true);//Read the first byte and send an ACK
rawLowByte = I2C_Master_Read(false); //shift the previously read value into the upper byte
I2C_Master_Stop();
// Calculate the pressure from the received data
uint16_t rawValue = ((uint16_t)rawLowByte << 8) | rawHighByte;
// Convert to [-351, 351] range
float value = (((float)rawValue - 81.0f) * 702.0f / 16128.0f) - 351.0f;
sprintf(pressure_str, "P: %f", value);
lcd_clear();
}
我认为你应该使用以下内容:
uint16_t rawValue = ( ( (uint16_t)rawHighByte << 8 ) | rawLowByte ) & 0x3FFF;
float value = ( ( rawValue - 0x2000 ) / (float)0x4000 ) * 702.0;
这都是猜测,因为你提供的信息很少,而你提供的信息很少是相互矛盾的。
错误 #1:转换公式不正确
您的输入预计应该在 [0,0x3FFF] ([0,16383]) 范围内。[1]
论文应该映射到输出 [-351,351]。
他们没有。
输入 | (((float)rawValue - 81.0f) * 702.0f / 16128.0f) - 351.0f |
---|---|
0x0000 | -354.525665283203125 |
0x3FFF | 358.57366943359375 |
要将 [0,0x3FFF] 映射到 [-351.0,351.0)[2],可以使用以下内容:
float value = ( ( rawValue - 0x2000 ) / (float)0x4000 ) * 702.0;
输入 | ( ( rawValue - 0x2000 ) / (float)0x4000 ) * 702.0 |
---|---|
0x0000 | -351 |
0x3FFF | 350.9571533203125 |
Bug #2:高低字节颠倒了
您正在使用
rawLowByte
作为高字节,而 rawHighByte
作为低字节。所以要么你用反了,要么名字错了。
前一种解释更有可能,因为你观察到的行为将直接导致反向使用它们。如果您将低字节用作高字节,则低字节中的 1 变化将导致
rawValue
中的 256 变化。
您使用了以下内容:
uint16_t rawValue = ( (uint16_t)rawLowByte << 8 ) | rawHighByte;
原始高字节 | 原始低字节 | ( (uint16_t)rawLowByte << 8 ) | rawHighByte | 价值 |
---|---|---|---|
0x0000 | -351 | ||
0x51 | 0x1F | 0x1F51 | -7.4981689453125 |
0x51 | 0x20 | 0x2051 | 3.4705810546875 |
0x51 | 0x21 | 0x2151 | 14.4393310546875 |
0x3FFF | 350.9571533203125 |
你可能应该使用以下内容:
uint16_t rawValue = ( (uint16_t)rawHighByte << 8 ) | rawLowByte;
原始高字节 | 原始低字节 | ( (uint16_t)rawHighByte << 8 ) | rawLowByte | 价值 |
---|---|---|---|
0x0000 | -351 | ||
0x51 | 0x1F | 0x511F | 538.7969970703125 |
0x51 | 0x20 | 0x5120 | 538.83984375 |
0x51 | 0x21 | 0x5121 | 538.8826904296875 |
0x3FFF | 350.9571533203125 |
错误#3:输入中剩余的额外位
但是通过上述修复,我们得到超出预期 [0,0x3FFF] 范围的
rawValue
值,因此我们得到超出预期 [-351.0,351.0) 范围的 value
值。
由于
rawValue
预计正好是低 14 位的整个范围,因此第 14 位和第 15 位可能用于其他目的,应该被过滤掉。这可以通过以下方式实现:
uint16_t rawValue = ( ( (uint16_t)rawHighByte << 8 ) | rawLowByte ) & 0x3FFF;
原始高字节 | 原始低字节 | ( ... ) & 0x3FFF | 价值 |
---|---|---|---|
0x0000 | -351 | ||
0x51 | 0x1F | 0x111F | -163.2030029296875 |
0x51 | 0x20 | 0x1120 | -163.16015625 |
0x51 | 0x21 | 0x1121 | -163.1173095703125 |
0x3FFF | 350.9571533203125 |