I2C协议有问题

tf7tbtn2  于 2023-04-05  发布在  其他
关注(0)|答案(1)|浏览(141)

我正在和几个朋友一起做一个项目,我试图解决一个问题,我在从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();
}
wfypjpf4

wfypjpf41#

我认为您应该使用以下内容:

uint16_t rawValue = ( ( (uint16_t)rawHighByte << 8 ) | rawLowByte ) & 0x3FFF;

float value = ( ( rawValue - 0x2000 ) / (float)0x4000 ) * 702.0;

这都是猜测,因为你提供的信息很少,你提供的信息是相互矛盾的。

Bug #1:换算公式不正确

您的输入应该在[0,0x 3FFF]([0,16383])范围内。[1]
这些应该Map到输出[-351,351]。
他们不会。
| 输入|(((float)rawValue - 81.0f)* 702.0f / 16128.0f)- 351.0f|
| --------------|--------------|
| 0x0000| -354.525665283203125 |
| 0x3FFF|358.57366943359375|
要将[0,0x 3FFF]Map到[-351.0,351.0)[2],可以使用以下内容:

float value = ( ( rawValue - 0x2000 ) / (float)0x4000 ) * 702.0;
输入((rawValue - 0x2000)/(float)0x4000)* 702.0
0x0000-351
0x3FFF350.9571533203125

Bug #2:高低字节颠倒

你使用rawLowByte作为高字节,rawHighByte作为低字节。所以你要么是用反了,要么是名字错了。
前一种解释更有可能,因为你观察到的行为是反向使用它们的直接结果。如果你使用低字节作为高字节,低字节中的1变化将导致rawValue中的256变化。
您使用了以下内容:

uint16_t rawValue = ( (uint16_t)rawLowByte << 8 ) | rawHighByte;
rawHighByterawLowByte((uint16_t)rawLowByte〈〈8)|rawHighByte价值
0x0000-351
0x510x1F0x1F51-7.4981689453125
0x510x200x20513.4705810546875
0x510x210x215114.4393310546875
0x3FFF350.9571533203125

您可能应该使用以下命令:

uint16_t rawValue = ( (uint16_t)rawHighByte << 8 ) | rawLowByte;
rawHighByterawLowByte((uint16_t)rawHighByte〈〈8)|rawLowByte价值
0x0000-351
0x510x1F0x511F538.7969970703125
0x510x200x5120538.83984375
0x510x210x5121538.8826904296875
0x3FFF350.9571533203125

Bug #3:输入中剩余的额外位

但是通过上面的修复,我们得到的rawValue值超出了预期的[0,0x 3FFF]范围,因此我们得到的value值超出了预期的[-351.0,351.0)范围。
由于rawValue预期正好是低14位的整个范围,所以位14和位15可能用于其他目的,应该被过滤掉。这可以通过以下方式实现:

uint16_t rawValue = ( ( (uint16_t)rawHighByte << 8 ) | rawLowByte ) & 0x3FFF;
rawHighByterawLowByte(...)& 0x3FFF价值
0x0000-351
0x510x1F0x111F-163.2030029296875
0x510x200x1120-163.16015625
0x510x210x1121-163.1173095703125
0x3FFF350.9571533203125

1.在问题中,你说输入在[81,16128]范围内。问题中的公式假设输入在[0,16127]范围内。在注解中,你说输入在[0,0x 3FFF]范围内。我使用了你提到的最后一个。
1.让范围的两端都包含在内是“棘手的”。

相关问题