You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在树莓派3B上通过I2C从Arduino从机读取浮点值(C语言)

解决树莓派WiringPi读取Arduino发送的float变量问题

我来帮你搞定这个问题!你已经走对了第一步——Arduino那边把float转成4字节数组发送的代码是正确的,问题出在树莓派这边只读取了1个字节,而float需要4个字节才能完整还原。下面给你两种可行的解决方案:

方案一:直接读取4字节并转换为float

因为WiringPi的wiringPiI2CRead()每次只能读取1个字节,所以我们需要循环读取4次,把所有字节存到缓冲区,再通过C语言的类型转换还原成float。

树莓派端C代码示例

#include <wiringPiI2C.h>
#include <stdint.h>
#include <string.h>

int main() {
    int fd;
    wiringPiSetup();
    fd = wiringPiI2CSetup(0x04); // 你的Arduino从机地址

    uint8_t floatBytes[4];
    // 循环读取4个字节,对应float的4个字节长度
    for (int i = 0; i < 4; i++) {
        floatBytes[i] = wiringPiI2CRead(fd);
    }

    // 方法1:使用union进行类型转换(更安全直观)
    union {
        uint8_t bytes[4];
        float value;
    } floatConverter;
    memcpy(floatConverter.bytes, floatBytes, 4);
    float result = floatConverter.value;

    // 方法2:直接通过指针强制转换(更简洁)
    // float result = *(float*)floatBytes;

    // 这里可以把result显示到LCD或者做其他处理
    // ui->lcdNumber->display(result); // 注意LCD可能需要格式化输出
    return 0;
}

关键注意点

  • Arduino和树莓派的float都是4字节IEEE754单精度浮点数,且两者都是小端字节序(AVR和ARM架构默认小端),所以不需要额外处理字节顺序,直接转换即可。
  • 确保Arduino的I2C从机逻辑正确:需要在setup()中注册onRequest回调,让树莓派发起读取请求时自动发送数据,比如:
    float floatNumber = 123.45; // 你的目标变量
    void setup() {
        Wire.begin(0x04);
        Wire.onRequest(sendData); // 注册请求回调
    }
    void sendData() {
        Wire.write((byte*)&floatNumber, 4);
    }
    

方案二:放大浮点值为整数后传输(适合对浮点转换敏感的场景)

如果担心浮点直接转换的兼容性,你可以把float放大为整数(比如乘以100保留两位小数),拆成多字节发送,树莓派端再还原。这种方式也能解决“数值超过255无法发送”的问题。

Arduino端代码调整

float floatNumber = 123.45;
void sendData() {
    // 放大100倍转为32位整数,避免溢出(如果数值更大可以调整倍数或用64位整数)
    int32_t scaledValue = (int32_t)(floatNumber * 100);
    Wire.write((byte*)&scaledValue, 4); // 发送4字节整数
}

树莓派端还原代码

#include <wiringPiI2C.h>
#include <stdint.h>

int main() {
    int fd;
    wiringPiSetup();
    fd = wiringPiI2CSetup(0x04);

    uint8_t intBytes[4];
    for (int i = 0; i < 4; i++) {
        intBytes[i] = wiringPiI2CRead(fd);
    }

    // 转换为32位整数
    int32_t scaledValue = *(int32_t*)intBytes;
    // 还原为浮点值
    float result = scaledValue / 100.0;

    // 后续处理逻辑
    return 0;
}

关键注意点

  • 选择合适的放大倍数:比如需要保留一位小数就乘10,三位乘1000,同时要确保放大后的数值不超过所选整数类型的范围(比如int32_t最大能到2147483647)。
  • 如果数值特别大,可以改用int64_t(8字节),对应Arduino端也用int64_t类型,发送8字节即可。

两种方案都能解决你的问题,推荐先试试方案一,更直接省心。如果遇到字节序相关的问题(概率极低),再考虑手动调整字节顺序。

内容的提问来源于stack exchange,提问作者VapeKop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:21:29