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

基于SPI在两块Arduino间传输浮点数的技术问题求助

解决Arduino SPI传输浮点数的重载调用错误及主从通信方案

嘿,我来帮你搞定这个SPI传输浮点数的问题,尤其是你碰到的那个重载调用错误~

先搞懂错误原因

你遇到的call of overloaded...错误,核心原因是Arduino的SPI库transfer()函数没有直接支持float类型的重载。默认情况下,transfer()只接受uint8_t(字节)、char或者uint16_t类型的参数,直接传float的话,编译器找不到对应的函数,就会报错。

解决方案:把浮点数拆成字节传输

float在Arduino里是4字节的(和uint32_t大小一致),我们可以用**共用体(union)**或者强制类型转换,把浮点数转换成字节数组,然后逐个字节传输,接收端再还原成float。

1. 静态值2.25的测试代码

先给你一套能跑通的主从测试代码,解决静态浮点数的传输问题:

主设备代码(比如Arduino Uno)
#include <SPI.h>

#define SLAVE_SELECT_PIN 10  // 选通从设备的引脚

// 共用体:实现float和字节数组的互转
union FloatConverter {
  float floatVal;
  uint8_t byteArr[4];
};

void setup() {
  SPI.begin();
  pinMode(SLAVE_SELECT_PIN, OUTPUT);
  Serial.begin(9600);
  digitalWrite(SLAVE_SELECT_PIN, HIGH); // 初始保持高电平,不选通从设备
}

void loop() {
  FloatConverter sendData;
  sendData.floatVal = 2.25; // 要传输的静态浮点数

  // 选通从设备,开始传输
  digitalWrite(SLAVE_SELECT_PIN, LOW);
  // 逐个发送4个字节
  for (int i = 0; i < 4; i++) {
    SPI.transfer(sendData.byteArr[i]);
  }
  digitalWrite(SLAVE_SELECT_PIN, HIGH); // 结束传输,取消选通

  Serial.print("已发送浮点数:");
  Serial.println(sendData.floatVal);
  delay(1000);
}
从设备代码(另一台Arduino Uno)
#include <SPI.h>

// 和主设备用一样的共用体
union FloatConverter {
  float floatVal;
  uint8_t byteArr[4];
};

void setup() {
  SPI.beginSlave(); // 初始化作为SPI从设备
  Serial.begin(9600);
}

void loop() {
  FloatConverter recvData;
  // 逐个接收4个字节,发送空字节0x00触发接收
  for (int i = 0; i < 4; i++) {
    recvData.byteArr[i] = SPI.transfer(0x00);
  }

  Serial.print("已接收浮点数:");
  Serial.println(recvData.floatVal);
  delay(1000);
}

拓展到主设备请求、从设备响应的模式

接下来适配你的最终需求:主设备发请求,从设备采集传感器数据再回传。只需要在上面的代码基础上做一点修改:

修改后的主设备代码

#include <SPI.h>

#define SLAVE_SELECT_PIN 10
#define REQUEST_CMD 0x01 // 定义请求数据的指令码

union FloatConverter {
  float floatVal;
  uint8_t byteArr[4];
};

void setup() {
  SPI.begin();
  pinMode(SLAVE_SELECT_PIN, OUTPUT);
  Serial.begin(9600);
  digitalWrite(SLAVE_SELECT_PIN, HIGH);
}

void loop() {
  FloatConverter recvSensorData;

  digitalWrite(SLAVE_SELECT_PIN, LOW);
  // 第一步:发送请求指令
  SPI.transfer(REQUEST_CMD);
  // 第二步:接收从设备回传的4个字节
  for (int i = 0; i < 4; i++) {
    recvSensorData.byteArr[i] = SPI.transfer(0x00);
  }
  digitalWrite(SLAVE_SELECT_PIN, HIGH);

  Serial.print("收到传感器数据:");
  Serial.println(recvSensorData.floatVal);
  delay(1000);
}

修改后的从设备代码

#include <SPI.h>

#define REQUEST_CMD 0x01

union FloatConverter {
  float floatVal;
  uint8_t byteArr[4];
};

// 模拟线性位移传感器读取函数,实际替换成你的传感器代码
float readLinearSensor() {
  // 这里可以替换成你的传感器读取逻辑,比如用analogRead后转换为浮点数
  return 3.75; // 模拟返回的传感器值
}

void setup() {
  SPI.beginSlave();
  Serial.begin(9600);
}

void loop() {
  // 先接收主设备的指令
  uint8_t receivedCmd = SPI.transfer(0x00);
  
  if (receivedCmd == REQUEST_CMD) {
    // 采集传感器数据
    FloatConverter sensorData;
    sensorData.floatVal = readLinearSensor();
    
    // 回传数据给主设备
    for (int i = 0; i < 4; i++) {
      SPI.transfer(sensorData.byteArr[i]);
    }
    
    Serial.print("已回传传感器数据:");
    Serial.println(sensorData.floatVal);
  }
}

额外注意事项

  • SPI参数一致性:主从设备的SPI模式(CPOL、CPHA)、时钟速度必须一致,默认是SPI_MODE0,如果修改了要两边同步。
  • 字节序问题:Arduino都是小端序,所以直接按数组顺序传输即可,不用额外处理字节序转换。
  • 精度排查:如果传输后浮点数精度不对,可以串口打印每个字节的十六进制值,对比发送和接收的字节是否完全一致,排查传输过程中的丢包问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:11:13