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这个类型,因此报错。
解决方法
有两种可行方案:
- 添加Arduino核心头文件引用:在
comm_modbus.h的最开头添加#include <Arduino.h>,因为byte的定义位于Arduino.h中,这样编译器就能识别byte类型。 - 使用标准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
相关产品推荐
相关产品推荐

