diff --git a/client.go b/client.go index ff569f7..3987fd2 100644 --- a/client.go +++ b/client.go @@ -1212,8 +1212,8 @@ func (mc *ModbusClient) readRegistersWithFunctionCode(addr uint16, quantity uint return } - // 16 * 16 * 40 - if quantity > 10240 { + // 16 * 40 + if quantity > 640 { err = ErrUnexpectedParameters mc.logger.Error("quantity of registers exceeds 10240") return diff --git a/rtu_transport.go b/rtu_transport.go index e799938..053d423 100644 --- a/rtu_transport.go +++ b/rtu_transport.go @@ -188,55 +188,6 @@ func (rt *rtuTransport) WriteResponse(res *pdu) (err error) { return } -func calculateModbusCRC16(data []byte) uint16 { - // 初始值 (标准 Modbus RTU) - var crc uint16 = 0xFFFF - - // 遍历所有需要校验的字节 - for _, b := range data { - // 1. 当前 CRC 异或当前字节 (注意:字节 b 转换为 uint16) - crc = crc ^ uint16(b) - - // 2. 8 次迭代进行位运算 - for i := 0; i < 8; i++ { - // 检查最低有效位 (LSB) - if crc&0x0001 != 0 { - // 如果 LSB 是 1: 右移一位,然后异或多项式 0xA001 - // 0xA001 是 0x8005 反射后的结果 - crc = (crc >> 1) ^ 0xA001 - } else { - // 如果 LSB 是 0: 直接右移一位 - crc = crc >> 1 - } - } - } - - // 3. 返回最终的 CRC 值 - return crc -} - -// 示例用法:使用此函数替换您原来的 crc.add/crc.value 逻辑 - -// 假设您的数据帧已完整接收到 rxbuf 中 -func checkCRC(rxbuf []byte, totalFrameSize int) bool { - // 1. 确定校验范围 (地址到数据结束) - crcEndIndex := totalFrameSize - 2 - dataToVerify := rxbuf[0:crcEndIndex] - - // 2. 使用模拟从机的函数计算 CRC - calculatedCRC := calculateModbusCRC16(dataToVerify) - - // 3. 提取接收到的 CRC (Little-Endian 顺序) - recvCRCLow := rxbuf[crcEndIndex] - recvCRCHigh := rxbuf[crcEndIndex+1] - - // 4. 重组接收到的 CRC - receivedCRC := (uint16(recvCRCHigh) << 8) | uint16(recvCRCLow) - - // 5. 比较 - return calculatedCRC == receivedCRC -} - // Waits for, reads and decodes a frame from the rtu link. func (rt *rtuTransport) readRTUFrame() (res *pdu, err error) { var rxbuf []byte diff --git a/tcp_transport.go b/tcp_transport.go index bdeeb0a..6bd7a88 100644 --- a/tcp_transport.go +++ b/tcp_transport.go @@ -154,8 +154,13 @@ func (tt *tcpTransport) readMBAPFrame() (p *pdu, txnId uint16, err error) { // the byte count includes the unit ID field, which we already have bytesNeeded-- + maxTCPFrameLen := maxTCPFrameLength + if rxbuf[1] == fcCustomize { + maxTCPFrameLen = 647 + } + // never read more than the max allowed frame length - if bytesNeeded+mbapHeaderLength > maxTCPFrameLength { + if bytesNeeded+mbapHeaderLength > maxTCPFrameLen { err = ErrProtocolError return }