ESP32在Arduino IDE中构建:未定义对“ CLASS :: function”的引用

如何解决ESP32在Arduino IDE中构建:未定义对“ CLASS :: function”的引用

我试图在Arduino IDE中为ESP32编写Sensirion SFM3000流量传感器的库。只要是一个草图,一切都会起作用。但是,当我尝试将其分离为.h和.cpp文件并将其实现为类时,在尝试编译草图时会遇到一些奇怪的错误。

sketch\SFM3019_HSKA.cpp.o:(.literal._ZN12SFM3019_HSKA17i2c_read_flow_CRCEv+0x4): undefined reference to `SFM3019_HSKA::crc8(unsigned char,unsigned char)'
sketch\SFM3019_HSKA.cpp.o: In function `SFM3019_HSKA::i2c_read_flow_CRC()':
sketch/SFM3019_HSKA.cpp:124: undefined reference to `SFM3019_HSKA::crc8(unsigned char,unsigned char)'
sketch/SFM3019_HSKA.cpp:128: undefined reference to `SFM3019_HSKA::crc8(unsigned char,unsigned char)'
collect2.exe: error: ld returned 1 exit status
exit status 1
Fehler beim Kompilieren für das Board ESP32 Dev Module.

据我所知,该错误消息是在i2c_read_flow_CRC()method在SFM3019_HSKA.cpp文件的最后一个调用中调用crc8()方法时发生的。到目前为止,我没有看到语法错误。但是我对如何继续调试也没有其他想法...

这是试图在以下库中使用该库的主要代码:

#include "SFM3019_HSKA.h"
#include <Wire.h>


SFM3019_HSKA::SensVal_s SensVal = {0,0};

SFM3019_HSKA SFM3019(0x2E); //Generate Object SFM3019 of class SFM3019_HSKA
 
void setup() {
  // put your setup code here,to run once:
  Serial.begin (115200);
  delay(100);  
  Wire.begin (21,22);   // for ESP32: SDA= GPIO_21 /SCL= GPIO_22

  SFM3019.i2c_device_check();  //checks if I2C device is available
  SFM3019.i2c_write(0x3608); //write 2Byte to start continuous measurement
  delay(100);
}

void loop() {
  // put your main code here,to run repeatedly:

  
  SensVal.flow = SFM3019.i2c_read_flow_CRC();  //read only Flow Bytes
  Serial.println(SensVal.flow,10);
  delay(100);
  SensVal = SFM3019.i2c_read_all();  //read all Sensor Bytes
  Serial.print("Flow: ");
  if (SensVal.flow >= 0) Serial.print(" "); //just for beauty reasons
  Serial.print(SensVal.flow,10);
  Serial.print("  Temp: ");
  Serial.print(SensVal.temp,3);
  Serial.print("  Statusword: ");
  Serial.print(SensVal.statusword,HEX);
  delay(400);
  Serial.println();
}

,这些是库文件: SFM3019_HSKA.h

#ifndef SFM3019_HSKA_H  // include guard
#define SFM3019_HSKA_H  

#include "Arduino.h"



    class SFM3019_HSKA {
      
    public: //can be accessed public

        SFM3019_HSKA(uint8_t i2cAddress); //Constructor
    
        //may be nicer in private if it works anyway
        typedef struct {float flow; float temp; int16_t statusword;} SensVal_s; //Struct for complete Sensor Readout
        SensVal_s SensVal = {0,0};  //initialize with 0

        int8_t i2c_device_check(); //function for Initialisation
        int8_t i2c_write(const uint16_t SendData); //function to write 16Bit Data to sensor
        SensVal_s i2c_read_all();  //function to read Flow,Temperature and Statusword
        float i2c_read_flow(); //function to only read Flow
        float i2c_read_flow_CRC(); //function to only read Flow with CRC check



    private:  //can only be accessed by functions oh same object
        
        uint8_t SFM3019addr = 46; //SFM3019 I2C Adress: 46 / 0x2E
        uint8_t crc8(const uint8_t data,uint8_t crc);  //fuction for CRC confirmation
    };

#endif

和导致错误的C ++文件: SFM3019_HSKA.cpp:

#include "SFM3019_HSKA.h" //when placed in same folder
//#include <SFM3019_HSKA.h> //when placed in standard library folder
#include <Wire.h>

//  some values needed for calculation of physical flow and temperature values
#define SFM3019Offset 24576
#define SFM3019ScaleFactorFlow 170.0 //needs to be a float,otherwise it will not calculate in float
#define SFM3019ScaleFactorTemp 200.0 //needs to be a float,otherwise it will not calculate in float


SFM3019_HSKA::SFM3019_HSKA(uint8_t i2cAddress)  //constructor
{
  //: mI2cAddress(i2cAddress)
  SFM3019addr = i2cAddress;
}


/*  checks if a Device at the desired address is responding with an ACK */
int8_t SFM3019_HSKA::i2c_device_check(){
  Wire.beginTransmission(SFM3019addr);    // Begin I2C transmission Address (i)
  if (Wire.endTransmission() == 0)  // Receive 0 = success (ACK response) 
    {
      Serial.print ("Found Seosor at address");
      Serial.print (SFM3019addr,DEC);
      Serial.print (" (0x");
      Serial.print (SFM3019addr,HEX);     // 7 bit address
      Serial.println (")");
      return 0;                        //0=device sent ACK
      
    }else{
      
      Serial.print ("Did not receive Acknowledge from I2C address ");
      Serial.print (SFM3019addr,HEX);     // 7 bit address
      Serial.println (")");
      return 1;                        //no ACK received
    }
}



/*  writes a 16bit "SendData" to I2C Bus Device "address" */
int8_t SFM3019_HSKA::i2c_write(const uint16_t SendData) {
    Wire.beginTransmission(SFM3019addr);
    //fill I2C outbuffer
    Wire.write((SendData>>8)& 0xFF); //isolate HighByte
    Wire.write(SendData & 0xFF); //isolate LowByte
    //send I2C outbuffer
    Wire.endTransmission();

    return 0;
}



/*  reads all 9 measurement bytes for flow,temp and status */
SFM3019_HSKA::SensVal_s SFM3019_HSKA::i2c_read_all(){
    SensVal_s SensVal = {0};  //create empty struct
    Wire.requestFrom(SFM3019addr,9,true); // Request 9byte (3x16bit + CRC) from the sensor
   //while(Wire.available()<3){};  //wait for all the data to be received //ATTENTION may be critical loop forever,however not using this may lead to an error,as the Buffer may be processed faster,then the input is read on I2C
    
    //get Flow Bytes
    int16_t flow = Wire.read()<<8;  //get Highbyte and shift 8bit to 8MSB
    flow = flow | Wire.read();      //get Lowbyte 8LSB
    byte CRCflow = Wire.read();         //get CRC Check Byte (you could do a data validy check with that)    
    //Serial.println(flow,HEX);    //raw values for debugging
    SensVal.flow = (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions        

    //get Temperature Bytes
    int16_t temp = Wire.read()<<8;  //get Highbyte and shift 8bit to 8MSB
    temp = temp | Wire.read();      //get Lowbyte 8LSB
    byte CRCtemp = Wire.read();         //get CRC Check Byte (you could do a data validy check with that)    
    //Serial.println(temp,HEX);    //raw values for debugging
    SensVal.temp = temp / SFM3019ScaleFactorTemp; //calculate the flow in slm as Datasheet mentions        

    //get StatusWord Bytes
    int16_t stat = Wire.read()<<8;  //get Highbyte and shift 8bit to 8MSB
    stat = stat | Wire.read();      //get Lowbyte 8LSB
    byte CRCstat = Wire.read();         //get CRC Check Byte (you could do a data validy check with that)    
    //Serial.println(stat,HEX);    //raw values for debugging
    SensVal.statusword = temp / SFM3019ScaleFactorTemp; //calculate the flow in slm as Datasheet mentions        

    //return all data
    return SensVal;
    
}



/*  reads only first 3 bytes for flow and does NO CRC!*/
float SFM3019_HSKA::i2c_read_flow(){
    Wire.requestFrom(SFM3019addr,3,true); // Request 9byte (2x16bit + CRC) from the sensor
    //while(Wire.available()<3){};  //wait for all the data to be received //ATTENTION may be critical loop forever,then the input is read on I2C
    int16_t flow = Wire.read()<<8;  //get Highbyte and shift 8bit to 8MSB
    flow = flow | Wire.read();      //get Lowbyte 8LSB
    byte CRC = Wire.read();         //get CRC Check Byte (you could do a data validy check with that)    
    //Serial.println(flow,HEX);    //raw values for debugging
    return (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions  
}

/*  reads only first 3 bytes for flow and DOES CRC*/
float SFM3019_HSKA::i2c_read_flow_CRC(){
    Wire.requestFrom(SFM3019addr,then the input is read on I2C
    uint8_t Highbyte = Wire.read();    //get Highbyte 8MSB
    uint8_t Lowbyte =  Wire.read();      //get Lowbyte 8LSB
    uint8_t CRC = Wire.read();         //get CRC Check Byte

    //Confirm CRC
    uint8_t mycrc = 0xFF; // initialize crc variable
    mycrc = crc8(Highbyte,mycrc); // let first byte through CRC calculation
    mycrc = crc8(Lowbyte,mycrc); // and the second byte too
    if (mycrc != CRC) { // check if the calculated and the received CRC byte matches
      //Serial.println("Error: wrong CRC");
      return -10000;  //extreme low value,so user knows somethig is wrong
    } else {
      //Serial.println("Success: identical CRC");
      int16_t flow = (Highbyte<<8) | Lowbyte; //stack the to bytes together as signed int16
      return (flow + SFM3019Offset) / SFM3019ScaleFactorFlow; //calculate the flow in slm as Datasheet mentions  
    }
}

/*  calculate a CRC Byte,(Cyclic Redundancy Check) */
uint8_t crc8(const uint8_t data,uint8_t crc)
{
     crc ^= data;                     //crc XOR data
     for ( uint8_t i = 8; i; --i ) {
       crc = ( crc & 0x80 )           
       ? (crc << 1) ^ 0x31
       : (crc << 1);
    }
  return crc;
}

对于任何关于如何继续的想法,我都会非常感激。

解决方法

/*  calculate a CRC Byte,(Cyclic Redundancy Check) */
uint8_t crc8(const uint8_t data,uint8_t crc)
{
     crc ^= data;                     //crc XOR data
     for ( uint8_t i = 8; i; --i ) {
       crc = ( crc & 0x80 )           
       ? (crc << 1) ^ 0x31
       : (crc << 1);
    }
  return crc;
}

需要为:

/*  calculate a CRC Byte,(Cyclic Redundancy Check) */
uint8_t SFM3019_HSKA::crc8(const uint8_t data,uint8_t crc)
{
     crc ^= data;                     //crc XOR data
     for ( uint8_t i = 8; i; --i ) {
       crc = ( crc & 0x80 )           
       ? (crc << 1) ^ 0x31
       : (crc << 1);
    }
  return crc;
}

您只是忘记将定义的方法标记为类的一部分。简单的错字错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-