【问题标题】:How convert raw data to useful temperature which comes from LSM303DLHC sensor如何将原始数据转换为来自 LSM303DLHC 传感器的有用温度
【发布时间】:2017-05-16 10:04:28
【问题描述】:

我使用 STM32F4 微控制器和 HAL 库。我想从 LSM303DLHC 传感器读取温度。以下代码负责此任务。

LSM303DLHC_Status_t LSM303DLHC_get_temp(int16_t *temp)
{
    uint8_t data_h = 0x00;
    uint8_t data_l = 0x00;
    uint16_t data_tmp = 0x00;
    uint8_t temp_enable = 0x00;

    if (HAL_I2C_Mem_Read(&hi2c1, LSM303_MAGNE_ADDRESS, TEMP_OUT_H_M, 1, &data_h, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }

    if (HAL_I2C_Mem_Read(&hi2c1, LSM303_MAGNE_ADDRESS, TEMP_OUT_L_M, 1, &data_l, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }

    data_tmp = (int16_t)((data_h << 8) | data_l);

    *temp = data_tmp/8;

    /*Enable temperature sensor*/
    if (HAL_I2C_Mem_Read(&hi2c1, LSM303_MAGNE_ADDRESS, CRA_REG_M, 1, &temp_enable, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }

    temp_enable |= (0x01 << 7);

    if (HAL_I2C_Mem_Write(&hi2c1, LSM303_MAGNE_ADDRESS, CRA_REG_M, 1, &temp_enable, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }
    /*End enable temperature sensor*/

    return LSM303DLHC_OK;
}

根据数据表和许多教程的温度是通过这个表达式计算的:

temp = (int16_t)((data_h << 8) | data_l);
temp = temp/8;

我所在的房间大约有 20 摄氏度。我的函数返回大约 128-136 的值。

我哪里做错了?

【问题讨论】:

  • 读取值并然后启用传感器看起来很奇怪。读取不应该介于启用和禁用之间吗?如果传感器在启用后需要时间来产生读数,也许还会有一些延迟。
  • 代码在移入符号位时会调用未定义的行为。
  • 每次测量后必须启用温度传感器。我第一次在 LSM303DLHC_init_temp() 中启用了温度传感器,然后在每次测量后我还启用了温度传感器。我在从寄存器(HAL_I2C_MEM_READ)读取之前尝试启用温度传感器,但结果是一样的。

标签: c embedded microcontroller temperature hal


【解决方案1】:

嗯,在我这边,当我在 20 摄氏度的房间中读取临时寄存器时,我得到以下值。

TH=255, TL=224

所以看来寄存器中的 0 值对应于 21 C(大约),当温度低于 21 C(TH 位 7 设置为 1)时,我可以使用代码获得正确的值:

printf("TH=%d, TL=%d\n", RegVal[0], RegVal[1]);
int16_t IntTemp = ((int16_t)RegVal[0] << 8) + RegVal[1];

printf("temp=%0.2f\n", (float)IntTemp / 128 + 21);

温度=20.75

【讨论】:

    【解决方案2】:

    您的值是 12 位值,但您将其视为 16 位值。

    在 LSM303DLHC 数据表中,温度寄存器如下所示: TEMP_OUT_H_M (31h), TEMP_OUT_L_M (32h)

    高位寄存器:TEMP11, TEMP10, ..., TEMP4 低位寄存器:TEMP3、TEMP2、TEMP1、TEMP0、-、-、-、-

    前 4 位 (LSB(!)) 没有温度值。

    正如您所写,您的温度值约为 0x130 (128-136)。在二进制中是 0000 0001 0011 0000。 前四位不相关。所以你必须阅读 0000 0001 0011 即 0x13 即十进制的 19。

    最好的问候,斯特凡

    编辑: 小心数据类型!您尝试将字节值移动 8。这将不起作用。 用 int 定义你的值:

    int16_t data_h = 0;
    int8_t data_l = 0;
    

    然后使用:

    *temp = ((int16_t)((data_h << 8) | data_l)>>4);
    

    提示:使用 MS Windows 计算器的编程模式,玩转二进制、十六进制和十进制数字。

    【讨论】:

    • 我已经介绍了您的建议,但 IMO 仍然无法正常工作。现在函数返回大约 50-60 摄氏度的温度。在我的房间里大约有 20 摄氏度。
    • data_h的地址用于读取数据。更改类型可能会导致问题。相反,data_h 应该在转换之前转换为 uint16_t
    【解决方案3】:
    # python
    
    # enable Temperature sensor 
    bus.write_byte_data(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M, 0x90)  
    
    ...
    # read register
    tempH = bus.read_byte_data(LSM303_ADDRESS_MAG, 0x31)
    tempL = bus.read_byte_data(LSM303_ADDRESS_MAG, 0x32)
    temp = (tempH << 8 ) +  tempL
    if temp > 32767:  # 2's complement
        temp -= 65536
    temperature = float( 20 + ( temp >> 4 )/ 8 )  # 16bit --> 12bit , 8LSB/deg
    

    【讨论】:

    • 添加纯代码答案很好,但如果您添加评论说明此代码将如何修复错误,那就太好了!
    猜你喜欢
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多