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

Arduino头文件声明byte*参数函数编译报错的原因及解决

Arduino Modbus项目中calcCRC函数参数声明编译错误问题

问题概述

在Arduino Modbus通信项目中,需传递字节数组给calcCRC函数以配合CRC16.h库(要求uint8_t类型数据)使用,但编译时触发错误。尝试用byte、array byte、byte*作为calcCRC的参数,均出现以下编译错误:

variable or field 'calcCRC' declared void

更新验证:注释掉头文件中的void calcCRC(byte*);声明及函数调用后编译正常;将参数类型改为int时错误也消失,因此确定问题出在头文件的byte*参数声明上。

项目代码

comm_modbus.cpp

#include <Crc16.h>
Crc16 crc; 

#include "Arduino_MachineControl.h"
using namespace machinecontrol;

#include "comm_modbus.h"

byte SlaveID = 0x01;
byte FunctionID;
byte addressHI;
byte addressLO;
byte quantityHI = 0x00;
byte quantityLO = 0x02;
byte totalByteWrite = 0x04;
byte Value24;
byte Value16;
byte Value8;
byte Value0;
byte crcHI;
byte crcLO;

int trameRecus[9];
int trameTraiter [9];
byte check[2];


void initModbus() {
    Serial.begin(9600);
    // Wait for Serial or start after 2.5s
    for (auto const timeout = millis() + 2500; !Serial && timeout < millis(); delay(500))
        ;

    delay(2500);
    Serial.println("Start RS485 initialization");

    // Set the PMC Communication Protocols to default config
    comm_protocols.init();

    // RS485/RS232 default config is:
    // - RS485 mode
    // - Half Duplex
    // - No A/B and Y/Z 120 Ohm termination enabled

    // Enable the RS485/RS232 system
    comm_protocols.rs485Enable(true);

    // Specify baudrate, and preamble and postamble times for RS485 communication
    comm_protocols.rs485.begin(19200,SERIAL_8E1 ,0, 500);
    // Start in receive mode
    comm_protocols.rs485.receive();

    Serial.println("Initialization done!");
}

long ModbusRead(unsigned int addrMB) {
      FunctionID = 0x03;
      addrModbus(addrMB);
      
      byte trame [] = {SlaveID,FunctionID,addressHI,addressLO,quantityHI,quantityLO};
      
      calcCRC(trame);
      
      byte trameComplet []={SlaveID,FunctionID,addressHI,addressLO,quantityHI,quantityLO,crcHI,crcLO};
      
        // Disable receive mode before transmission
        comm_protocols.rs485.noReceive();

        comm_protocols.rs485.beginTransmission();

        comm_protocols.rs485.write(trameComplet[0]);
        comm_protocols.rs485.write(trameComplet[1]);
        comm_protocols.rs485.write(trameComplet[2]);
        comm_protocols.rs485.write(trameComplet[3]);
        comm_protocols.rs485.write(trameComplet[4]);
        comm_protocols.rs485.write(trameComplet[5]);
        comm_protocols.rs485.write(trameComplet[6]);
        comm_protocols.rs485.write(trameComplet[7]);

        comm_protocols.rs485.endTransmission();

        // Re-enable receive mode after transmission
        comm_protocols.rs485.receive();
        
    auto const timeout = millis() + 500;
    while (comm_protocols.rs485.available() < 9) {
        if (millis()> timeout) {
          Serial.println("communication timeout!");
          Serial.println("erreur : ");
          while(comm_protocols.rs485.available()) {
            Serial.println(comm_protocols.rs485.read());
          }
          break;
        }
      }
    if (comm_protocols.rs485.available()==9) {
    
      long value;
      reception();
      value = VARvalue();
      return value;
    }
}

void ModbusWrite(unsigned int addrMB, long ValueMB) {
  
  FunctionID = 0x10;
  addrModbus(addrMB);
  ValueModbus(ValueMB);
  
  byte trame [] = {SlaveID,FunctionID,addressHI,addressLO,quantityHI,quantityLO,totalByteWrite,Value24,Value16,Value8,Value0};
  
  calcCRC(trame);

   byte trameComplet []={SlaveID,FunctionID,addressHI,addressLO,quantityHI,quantityLO,totalByteWrite,Value24,Value16,Value8,Value0,crcHI,crcLO};

   comm_protocols.rs485.noReceive();

        comm_protocols.rs485.beginTransmission();

        comm_protocols.rs485.write(trameComplet[0]);
        comm_protocols.rs485.write(trameComplet[1]);
        comm_protocols.rs485.write(trameComplet[2]);
        comm_protocols.rs485.write(trameComplet[3]);
        comm_protocols.rs485.write(trameComplet[4]);
        comm_protocols.rs485.write(trameComplet[5]);
        comm_protocols.rs485.write(trameComplet[6]);
        comm_protocols.rs485.write(trameComplet[7]);
        comm_protocols.rs485.write(trameComplet[8]);
        comm_protocols.rs485.write(trameComplet[9]);
        comm_protocols.rs485.write(trameComplet[10]);

        comm_protocols.rs485.endTransmission();

        // Re-enable receive mode after transmission
        comm_protocols.rs485.receive();
}

void addrModbus(unsigned int addresseMB) {
 
  addressHI = (addresseMB >> 8) & 0xFF; //highbyte
  addressLO = (addresseMB & 0xFF);      //lowbyte
}

void ValueModbus(long valMB) {
 
    Value24 = (valMB & 0xFF000000) >> 24; 
    Value16 = (valMB & 0x00FF0000) >> 16; 
    Value8  = (valMB & 0x0000FF00) >> 8; 
    Value0  = valMB & 0xFF; 
    
}

void calcCRC(byte *trame) {
  
   unsigned short crcTrame;
   int sizeTrame= sizeof(trame);
    
    crc.clearCrc();
    for(int i=0;i< sizeTrame;i++)
    {
      Serial.print("byte ");
      Serial.print(i);
      Serial.print(" = ");
      Serial.println(trame[i],HEX);
     crc.updateCrc(trame[i]);
    }
    
    crcTrame = crc.Modbus(trame,0,sizeTrame);

    check[1] = (crcTrame >> 8) & 0xFF; //highbyte
    check[0] = (crcTrame & 0xFF);      //lowbyte

    crcHI = check[0],HEX;
    crcLO = check[1],HEX;

    Serial.print("Modbus crcHI = 0x");    
    Serial.println(crcHI,HEX);
    Serial.print("Modbus crcLO = 0x");    
    Serial.println(crcLO,HEX);
}

long VARvalue() {
  long Value = 0;
  int expo = 0;
  int multi = 0;
  for( int i = 3 ;i <= trameRecus[2]+2;i++) {
    expo = 6-i;
    multi = pow(256,expo);
    trameRecus[i]= trameRecus[i] * multi;
    Value = Value + trameRecus[i];
  }
  Serial.print("valeur reel = ");
  Serial.println(Value);
  return Value;
}

void reception() {
 
  int compteur = 0;
  byte ValueModbus;
  
  while (comm_protocols.rs485.available()> 0) {
      ValueModbus = comm_protocols.rs485.read();
      Serial.println("Reception :");
      Serial.println(ValueModbus);
      trameRecus[compteur] = ValueModbus;
      
      compteur++;
  }
}

comm_modbus.h

void initModbus();
long ModbusRead(unsigned int);
void ModbusWrite(unsigned int, long);
void addrModbus(unsigned int);
void ValueModbus(long);
void calcCRC(byte*);
long VARvalue();
void reception();

问题原因与解决方法

原因

byte是Arduino核心库中定义的typedef别名(等价于标准C类型uint8_t),但头文件comm_modbus.h中没有包含定义byte类型的头文件,编译器无法识别byte这个类型,因此报错。

解决方法

有两种可行方案:

  1. 添加Arduino核心头文件引用:在comm_modbus.h的最开头添加#include <Arduino.h>,因为byte的定义位于Arduino.h中,这样编译器就能识别byte类型。
  2. 使用标准C类型替代:将头文件和cpp文件中的byte统一替换为uint8_t(CRC16库要求的类型),修改头文件中的声明为void calcCRC(uint8_t*);,cpp文件中的函数定义也对应改为void calcCRC(uint8_t *trame),这样既符合库的要求,也避免依赖Arduino的自定义typedef。

额外注意点

calcCRC函数中存在一个逻辑错误:

int sizeTrame= sizeof(trame);

这里trame是指针类型,sizeof(trame)得到的是指针本身的大小(通常为2或4字节),而不是传入数组的实际长度,会导致CRC计算不完整。需要修改函数,额外传递数组长度参数:

  • 头文件声明改为:void calcCRC(uint8_t* trame, int size);
  • cpp函数定义改为:void calcCRC(uint8_t *trame, int sizeTrame)
  • 调用时传递数组长度:calcCRC(trame, sizeof(trame));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 03:48:35