• 理解C语言中的位操作和整数类型:一个温度传感器读取问题的解析


    前言:当我们编写嵌入式系统的代码时,我们经常需要使用位操作来处理硬件设备的数据。然而,如果我们对C语言的位操作和整数类型不完全理解,可能会遇到一些难以理解的问题。在这篇博客中,我将通过一个实际的例子来解释这些概念,并提供一个解决方案。

    问题描述

    我们有一个函数,用于读取一个温度传感器(MPU6050)的数据。这个函数通过I2C接口从传感器读取两个字节的数据,然后通过位操作将这两个字节合并成一个16位的整数。然后,这个整数被转换为实际的温度值。

    然而,我们发现了一个问题。当我们将这个16位的整数定义为int类型时,我们得到的温度值大约是208。但是当我们将它定义为int16_t类型时,我们得到的温度值是25,这是一个正常的温度值。那么,为什么会出现这种情况呢?

    问题分析

    在C语言中,int类型的大小是平台相关的,它可以是16位,32位,或64位。而int16_t是一个明确的16位整数。在我们的例子中,问题的关键在于位操作。

    我们的代码中有这样一行:(data[0] << 8 | data[1])。这是一个位操作,它将data[0]左移8位,然后与data[1]进行位或操作。如果data[0]的最高位(符号位)是1(也就是说,它是一个负数),那么在32位或64位的int中,这个位移操作会将高位填充为1,这是因为C语言的位移操作是带符号的。这将导致整个int变得非常大,这就解释了为什么我们看到的结果是208。

    而当我们将这个16位的整数定义为int16_t类型时,位移操作只会在16位内进行,因此即使data[0]的最高位是1,也不会影响整数的其他位,因此我们得到了正确的结果。

    解决方案

    解决这个问题的方法很简单:我们需要明确地使用int16_t类型来定义我们的16位整数。这样,无论我们的平台的int类型是多少位,我们都可以得到正确的结果。

    这是修正后的代码:

    void MPU6050_Read_Temperature(double *temperature) {
        uint8_t data[2];
        M_I2C_Reicive_Byte(MPU6050_TEMP_OUT_H, &data[0]);
        M_I2C_Reicive_Byte(MPU6050_TEMP_OUT_L, &data[1]);
        int16_t sum = (data[0] << 8 | data[1]);
        *temperature = sum / 340.0 + 36.53;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结论

    在使用位操作运算符时,应当注意所使用变量类型,避免将符号数误判为数据写入

  • 相关阅读:
    【毕业设计】基于红外热释电的房间人数计数系统 - 单片机 物联网嵌入式
    Python的打包神器—Nuitka!
    亚马逊红人买家秀关联视频是合规安全提升转化的有力工具
    安卓RadioButton设置图片大小
    Flink sql 实现 -connection-clickhouse的 source和 sink
    Linux中常用的性能分析工具
    SpringBoot整合Junit
    深入学习 Redis Sentinel - 基于 DockerCompose 编排哨兵分布式架构,理解工作原理
    架构-三层架构:三层架构
    Bytebase 2023 第三季度回顾
  • 原文地址:https://blog.csdn.net/qq_61637982/article/details/138171739